Bug Summary

File:src/usr.bin/tmux/tty-keys.c
Warning:line 1547, column 17
The left operand of '==' is a garbage value due to array index out of bounds

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tty-keys.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/tmux/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.bin/tmux -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/tmux/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/tmux/tty-keys.c
1/* $OpenBSD: tty-keys.c,v 1.172 2023/09/08 07:05:06 nicm Exp $ */
2
3/*
4 * Copyright (c) 2007 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/time.h>
21
22#include <netinet/in.h>
23
24#include <ctype.h>
25#include <limits.h>
26#include <resolv.h>
27#include <stdlib.h>
28#include <string.h>
29#include <termios.h>
30#include <unistd.h>
31
32#include "tmux.h"
33
34/*
35 * Handle keys input from the outside terminal. tty_default_*_keys[] are a base
36 * table of supported keys which are looked up in terminfo(5) and translated
37 * into a ternary tree.
38 */
39
40static void tty_keys_add1(struct tty_key **, const char *, key_code);
41static void tty_keys_add(struct tty *, const char *, key_code);
42static void tty_keys_free1(struct tty_key *);
43static struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
44 size_t *);
45static struct tty_key *tty_keys_find(struct tty *, const char *, size_t,
46 size_t *);
47static int tty_keys_next1(struct tty *, const char *, size_t, key_code *,
48 size_t *, int);
49static void tty_keys_callback(int, short, void *);
50static int tty_keys_extended_key(struct tty *, const char *, size_t,
51 size_t *, key_code *);
52static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *,
53 struct mouse_event *);
54static int tty_keys_clipboard(struct tty *, const char *, size_t,
55 size_t *);
56static int tty_keys_device_attributes(struct tty *, const char *, size_t,
57 size_t *);
58static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
59 size_t *);
60static int tty_keys_extended_device_attributes(struct tty *, const char *,
61 size_t, size_t *);
62static int tty_keys_colours(struct tty *, const char *, size_t, size_t *);
63
64/* A key tree entry. */
65struct tty_key {
66 char ch;
67 key_code key;
68
69 struct tty_key *left;
70 struct tty_key *right;
71
72 struct tty_key *next;
73};
74
75/* Default raw keys. */
76struct tty_default_key_raw {
77 const char *string;
78 key_code key;
79};
80static const struct tty_default_key_raw tty_default_raw_keys[] = {
81 /* Application escape. */
82 { "\033O[", '\033' },
83
84 /*
85 * Numeric keypad. Just use the vt100 escape sequences here and always
86 * put the terminal into keypad_xmit mode. Translation of numbers
87 * mode/applications mode is done in input-keys.c.
88 */
89 { "\033Oo", KEYC_KP_SLASH|KEYC_KEYPAD0x02000000000000ULL },
90 { "\033Oj", KEYC_KP_STAR|KEYC_KEYPAD0x02000000000000ULL },
91 { "\033Om", KEYC_KP_MINUS|KEYC_KEYPAD0x02000000000000ULL },
92 { "\033Ow", KEYC_KP_SEVEN|KEYC_KEYPAD0x02000000000000ULL },
93 { "\033Ox", KEYC_KP_EIGHT|KEYC_KEYPAD0x02000000000000ULL },
94 { "\033Oy", KEYC_KP_NINE|KEYC_KEYPAD0x02000000000000ULL },
95 { "\033Ok", KEYC_KP_PLUS|KEYC_KEYPAD0x02000000000000ULL },
96 { "\033Ot", KEYC_KP_FOUR|KEYC_KEYPAD0x02000000000000ULL },
97 { "\033Ou", KEYC_KP_FIVE|KEYC_KEYPAD0x02000000000000ULL },
98 { "\033Ov", KEYC_KP_SIX|KEYC_KEYPAD0x02000000000000ULL },
99 { "\033Oq", KEYC_KP_ONE|KEYC_KEYPAD0x02000000000000ULL },
100 { "\033Or", KEYC_KP_TWO|KEYC_KEYPAD0x02000000000000ULL },
101 { "\033Os", KEYC_KP_THREE|KEYC_KEYPAD0x02000000000000ULL },
102 { "\033OM", KEYC_KP_ENTER|KEYC_KEYPAD0x02000000000000ULL },
103 { "\033Op", KEYC_KP_ZERO|KEYC_KEYPAD0x02000000000000ULL },
104 { "\033On", KEYC_KP_PERIOD|KEYC_KEYPAD0x02000000000000ULL },
105
106 /* Arrow keys. */
107 { "\033OA", KEYC_UP|KEYC_CURSOR0x04000000000000ULL },
108 { "\033OB", KEYC_DOWN|KEYC_CURSOR0x04000000000000ULL },
109 { "\033OC", KEYC_RIGHT|KEYC_CURSOR0x04000000000000ULL },
110 { "\033OD", KEYC_LEFT|KEYC_CURSOR0x04000000000000ULL },
111
112 { "\033[A", KEYC_UP|KEYC_CURSOR0x04000000000000ULL },
113 { "\033[B", KEYC_DOWN|KEYC_CURSOR0x04000000000000ULL },
114 { "\033[C", KEYC_RIGHT|KEYC_CURSOR0x04000000000000ULL },
115 { "\033[D", KEYC_LEFT|KEYC_CURSOR0x04000000000000ULL },
116
117 /*
118 * Meta arrow keys. These do not get the IMPLIED_META flag so they
119 * don't match the xterm-style meta keys in the output tree - Escape+Up
120 * should stay as Escape+Up and not become M-Up.
121 */
122 { "\033\033OA", KEYC_UP|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
123 { "\033\033OB", KEYC_DOWN|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
124 { "\033\033OC", KEYC_RIGHT|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
125 { "\033\033OD", KEYC_LEFT|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
126
127 { "\033\033[A", KEYC_UP|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
128 { "\033\033[B", KEYC_DOWN|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
129 { "\033\033[C", KEYC_RIGHT|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
130 { "\033\033[D", KEYC_LEFT|KEYC_CURSOR0x04000000000000ULL|KEYC_META0x00100000000000ULL },
131
132 /* Other xterm keys. */
133 { "\033OH", KEYC_HOME },
134 { "\033OF", KEYC_END },
135
136 { "\033\033OH", KEYC_HOME|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
137 { "\033\033OF", KEYC_END|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
138
139 { "\033[H", KEYC_HOME },
140 { "\033[F", KEYC_END },
141
142 { "\033\033[H", KEYC_HOME|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
143 { "\033\033[F", KEYC_END|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
144
145 /* rxvt arrow keys. */
146 { "\033Oa", KEYC_UP|KEYC_CTRL0x00200000000000ULL },
147 { "\033Ob", KEYC_DOWN|KEYC_CTRL0x00200000000000ULL },
148 { "\033Oc", KEYC_RIGHT|KEYC_CTRL0x00200000000000ULL },
149 { "\033Od", KEYC_LEFT|KEYC_CTRL0x00200000000000ULL },
150
151 { "\033[a", KEYC_UP|KEYC_SHIFT0x00400000000000ULL },
152 { "\033[b", KEYC_DOWN|KEYC_SHIFT0x00400000000000ULL },
153 { "\033[c", KEYC_RIGHT|KEYC_SHIFT0x00400000000000ULL },
154 { "\033[d", KEYC_LEFT|KEYC_SHIFT0x00400000000000ULL },
155
156 /* rxvt function keys. */
157 { "\033[11~", KEYC_F1 },
158 { "\033[12~", KEYC_F2 },
159 { "\033[13~", KEYC_F3 },
160 { "\033[14~", KEYC_F4 },
161 { "\033[15~", KEYC_F5 },
162 { "\033[17~", KEYC_F6 },
163 { "\033[18~", KEYC_F7 },
164 { "\033[19~", KEYC_F8 },
165 { "\033[20~", KEYC_F9 },
166 { "\033[21~", KEYC_F10 },
167
168 { "\033[23~", KEYC_F1|KEYC_SHIFT0x00400000000000ULL },
169 { "\033[24~", KEYC_F2|KEYC_SHIFT0x00400000000000ULL },
170 { "\033[25~", KEYC_F3|KEYC_SHIFT0x00400000000000ULL },
171 { "\033[26~", KEYC_F4|KEYC_SHIFT0x00400000000000ULL },
172 { "\033[28~", KEYC_F5|KEYC_SHIFT0x00400000000000ULL },
173 { "\033[29~", KEYC_F6|KEYC_SHIFT0x00400000000000ULL },
174 { "\033[31~", KEYC_F7|KEYC_SHIFT0x00400000000000ULL },
175 { "\033[32~", KEYC_F8|KEYC_SHIFT0x00400000000000ULL },
176 { "\033[33~", KEYC_F9|KEYC_SHIFT0x00400000000000ULL },
177 { "\033[34~", KEYC_F10|KEYC_SHIFT0x00400000000000ULL },
178 { "\033[23$", KEYC_F11|KEYC_SHIFT0x00400000000000ULL },
179 { "\033[24$", KEYC_F12|KEYC_SHIFT0x00400000000000ULL },
180
181 { "\033[11^", KEYC_F1|KEYC_CTRL0x00200000000000ULL },
182 { "\033[12^", KEYC_F2|KEYC_CTRL0x00200000000000ULL },
183 { "\033[13^", KEYC_F3|KEYC_CTRL0x00200000000000ULL },
184 { "\033[14^", KEYC_F4|KEYC_CTRL0x00200000000000ULL },
185 { "\033[15^", KEYC_F5|KEYC_CTRL0x00200000000000ULL },
186 { "\033[17^", KEYC_F6|KEYC_CTRL0x00200000000000ULL },
187 { "\033[18^", KEYC_F7|KEYC_CTRL0x00200000000000ULL },
188 { "\033[19^", KEYC_F8|KEYC_CTRL0x00200000000000ULL },
189 { "\033[20^", KEYC_F9|KEYC_CTRL0x00200000000000ULL },
190 { "\033[21^", KEYC_F10|KEYC_CTRL0x00200000000000ULL },
191 { "\033[23^", KEYC_F11|KEYC_CTRL0x00200000000000ULL },
192 { "\033[24^", KEYC_F12|KEYC_CTRL0x00200000000000ULL },
193
194 { "\033[11@", KEYC_F1|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
195 { "\033[12@", KEYC_F2|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
196 { "\033[13@", KEYC_F3|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
197 { "\033[14@", KEYC_F4|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
198 { "\033[15@", KEYC_F5|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
199 { "\033[17@", KEYC_F6|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
200 { "\033[18@", KEYC_F7|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
201 { "\033[19@", KEYC_F8|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
202 { "\033[20@", KEYC_F9|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
203 { "\033[21@", KEYC_F10|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
204 { "\033[23@", KEYC_F11|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
205 { "\033[24@", KEYC_F12|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
206
207 /* Focus tracking. */
208 { "\033[I", KEYC_FOCUS_IN },
209 { "\033[O", KEYC_FOCUS_OUT },
210
211 /* Paste keys. */
212 { "\033[200~", KEYC_PASTE_START },
213 { "\033[201~", KEYC_PASTE_END },
214
215 /* Extended keys. */
216 { "\033[1;5Z", '\011'|KEYC_CTRL0x00200000000000ULL|KEYC_SHIFT0x00400000000000ULL },
217};
218
219/* Default xterm keys. */
220struct tty_default_key_xterm {
221 const char *template;
222 key_code key;
223};
224static const struct tty_default_key_xterm tty_default_xterm_keys[] = {
225 { "\033[1;_P", KEYC_F1 },
226 { "\033O1;_P", KEYC_F1 },
227 { "\033O_P", KEYC_F1 },
228 { "\033[1;_Q", KEYC_F2 },
229 { "\033O1;_Q", KEYC_F2 },
230 { "\033O_Q", KEYC_F2 },
231 { "\033[1;_R", KEYC_F3 },
232 { "\033O1;_R", KEYC_F3 },
233 { "\033O_R", KEYC_F3 },
234 { "\033[1;_S", KEYC_F4 },
235 { "\033O1;_S", KEYC_F4 },
236 { "\033O_S", KEYC_F4 },
237 { "\033[15;_~", KEYC_F5 },
238 { "\033[17;_~", KEYC_F6 },
239 { "\033[18;_~", KEYC_F7 },
240 { "\033[19;_~", KEYC_F8 },
241 { "\033[20;_~", KEYC_F9 },
242 { "\033[21;_~", KEYC_F10 },
243 { "\033[23;_~", KEYC_F11 },
244 { "\033[24;_~", KEYC_F12 },
245 { "\033[1;_A", KEYC_UP },
246 { "\033[1;_B", KEYC_DOWN },
247 { "\033[1;_C", KEYC_RIGHT },
248 { "\033[1;_D", KEYC_LEFT },
249 { "\033[1;_H", KEYC_HOME },
250 { "\033[1;_F", KEYC_END },
251 { "\033[5;_~", KEYC_PPAGE },
252 { "\033[6;_~", KEYC_NPAGE },
253 { "\033[2;_~", KEYC_IC },
254 { "\033[3;_~", KEYC_DC },
255};
256static const key_code tty_default_xterm_modifiers[] = {
257 0,
258 0,
259 KEYC_SHIFT0x00400000000000ULL,
260 KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL,
261 KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL,
262 KEYC_CTRL0x00200000000000ULL,
263 KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL,
264 KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL,
265 KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL,
266 KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL
267};
268
269/*
270 * Default terminfo(5) keys. Any keys that have builtin modifiers (that is,
271 * where the key itself contains the modifiers) has the KEYC_XTERM flag set so
272 * a leading escape is not treated as meta (and probably removed).
273 */
274struct tty_default_key_code {
275 enum tty_code_code code;
276 key_code key;
277};
278static const struct tty_default_key_code tty_default_code_keys[] = {
279 /* Function keys. */
280 { TTYC_KF1, KEYC_F1 },
281 { TTYC_KF2, KEYC_F2 },
282 { TTYC_KF3, KEYC_F3 },
283 { TTYC_KF4, KEYC_F4 },
284 { TTYC_KF5, KEYC_F5 },
285 { TTYC_KF6, KEYC_F6 },
286 { TTYC_KF7, KEYC_F7 },
287 { TTYC_KF8, KEYC_F8 },
288 { TTYC_KF9, KEYC_F9 },
289 { TTYC_KF10, KEYC_F10 },
290 { TTYC_KF11, KEYC_F11 },
291 { TTYC_KF12, KEYC_F12 },
292
293 { TTYC_KF13, KEYC_F1|KEYC_SHIFT0x00400000000000ULL },
294 { TTYC_KF14, KEYC_F2|KEYC_SHIFT0x00400000000000ULL },
295 { TTYC_KF15, KEYC_F3|KEYC_SHIFT0x00400000000000ULL },
296 { TTYC_KF16, KEYC_F4|KEYC_SHIFT0x00400000000000ULL },
297 { TTYC_KF17, KEYC_F5|KEYC_SHIFT0x00400000000000ULL },
298 { TTYC_KF18, KEYC_F6|KEYC_SHIFT0x00400000000000ULL },
299 { TTYC_KF19, KEYC_F7|KEYC_SHIFT0x00400000000000ULL },
300 { TTYC_KF20, KEYC_F8|KEYC_SHIFT0x00400000000000ULL },
301 { TTYC_KF21, KEYC_F9|KEYC_SHIFT0x00400000000000ULL },
302 { TTYC_KF22, KEYC_F10|KEYC_SHIFT0x00400000000000ULL },
303 { TTYC_KF23, KEYC_F11|KEYC_SHIFT0x00400000000000ULL },
304 { TTYC_KF24, KEYC_F12|KEYC_SHIFT0x00400000000000ULL },
305
306 { TTYC_KF25, KEYC_F1|KEYC_CTRL0x00200000000000ULL },
307 { TTYC_KF26, KEYC_F2|KEYC_CTRL0x00200000000000ULL },
308 { TTYC_KF27, KEYC_F3|KEYC_CTRL0x00200000000000ULL },
309 { TTYC_KF28, KEYC_F4|KEYC_CTRL0x00200000000000ULL },
310 { TTYC_KF29, KEYC_F5|KEYC_CTRL0x00200000000000ULL },
311 { TTYC_KF30, KEYC_F6|KEYC_CTRL0x00200000000000ULL },
312 { TTYC_KF31, KEYC_F7|KEYC_CTRL0x00200000000000ULL },
313 { TTYC_KF32, KEYC_F8|KEYC_CTRL0x00200000000000ULL },
314 { TTYC_KF33, KEYC_F9|KEYC_CTRL0x00200000000000ULL },
315 { TTYC_KF34, KEYC_F10|KEYC_CTRL0x00200000000000ULL },
316 { TTYC_KF35, KEYC_F11|KEYC_CTRL0x00200000000000ULL },
317 { TTYC_KF36, KEYC_F12|KEYC_CTRL0x00200000000000ULL },
318
319 { TTYC_KF37, KEYC_F1|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
320 { TTYC_KF38, KEYC_F2|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
321 { TTYC_KF39, KEYC_F3|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
322 { TTYC_KF40, KEYC_F4|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
323 { TTYC_KF41, KEYC_F5|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
324 { TTYC_KF42, KEYC_F6|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
325 { TTYC_KF43, KEYC_F7|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
326 { TTYC_KF44, KEYC_F8|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
327 { TTYC_KF45, KEYC_F9|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
328 { TTYC_KF46, KEYC_F10|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
329 { TTYC_KF47, KEYC_F11|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
330 { TTYC_KF48, KEYC_F12|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
331
332 { TTYC_KF49, KEYC_F1|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
333 { TTYC_KF50, KEYC_F2|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
334 { TTYC_KF51, KEYC_F3|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
335 { TTYC_KF52, KEYC_F4|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
336 { TTYC_KF53, KEYC_F5|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
337 { TTYC_KF54, KEYC_F6|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
338 { TTYC_KF55, KEYC_F7|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
339 { TTYC_KF56, KEYC_F8|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
340 { TTYC_KF57, KEYC_F9|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
341 { TTYC_KF58, KEYC_F10|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
342 { TTYC_KF59, KEYC_F11|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
343 { TTYC_KF60, KEYC_F12|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
344
345 { TTYC_KF61, KEYC_F1|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_SHIFT0x00400000000000ULL },
346 { TTYC_KF62, KEYC_F2|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_SHIFT0x00400000000000ULL },
347 { TTYC_KF63, KEYC_F3|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_SHIFT0x00400000000000ULL },
348
349 { TTYC_KICH1, KEYC_IC },
350 { TTYC_KDCH1, KEYC_DC },
351 { TTYC_KHOME, KEYC_HOME },
352 { TTYC_KEND, KEYC_END },
353 { TTYC_KNP, KEYC_NPAGE },
354 { TTYC_KPP, KEYC_PPAGE },
355 { TTYC_KCBT, KEYC_BTAB },
356
357 /* Arrow keys from terminfo. */
358 { TTYC_KCUU1, KEYC_UP|KEYC_CURSOR0x04000000000000ULL },
359 { TTYC_KCUD1, KEYC_DOWN|KEYC_CURSOR0x04000000000000ULL },
360 { TTYC_KCUB1, KEYC_LEFT|KEYC_CURSOR0x04000000000000ULL },
361 { TTYC_KCUF1, KEYC_RIGHT|KEYC_CURSOR0x04000000000000ULL },
362
363 /* Key and modifier capabilities. */
364 { TTYC_KDC2, KEYC_DC|KEYC_SHIFT0x00400000000000ULL },
365 { TTYC_KDC3, KEYC_DC|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
366 { TTYC_KDC4, KEYC_DC|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
367 { TTYC_KDC5, KEYC_DC|KEYC_CTRL0x00200000000000ULL },
368 { TTYC_KDC6, KEYC_DC|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
369 { TTYC_KDC7, KEYC_DC|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
370 { TTYC_KIND, KEYC_DOWN|KEYC_SHIFT0x00400000000000ULL },
371 { TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT0x00400000000000ULL },
372 { TTYC_KDN3, KEYC_DOWN|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
373 { TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
374 { TTYC_KDN5, KEYC_DOWN|KEYC_CTRL0x00200000000000ULL },
375 { TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
376 { TTYC_KDN7, KEYC_DOWN|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
377 { TTYC_KEND2, KEYC_END|KEYC_SHIFT0x00400000000000ULL },
378 { TTYC_KEND3, KEYC_END|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
379 { TTYC_KEND4, KEYC_END|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
380 { TTYC_KEND5, KEYC_END|KEYC_CTRL0x00200000000000ULL },
381 { TTYC_KEND6, KEYC_END|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
382 { TTYC_KEND7, KEYC_END|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
383 { TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT0x00400000000000ULL },
384 { TTYC_KHOM3, KEYC_HOME|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
385 { TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
386 { TTYC_KHOM5, KEYC_HOME|KEYC_CTRL0x00200000000000ULL },
387 { TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
388 { TTYC_KHOM7, KEYC_HOME|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
389 { TTYC_KIC2, KEYC_IC|KEYC_SHIFT0x00400000000000ULL },
390 { TTYC_KIC3, KEYC_IC|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
391 { TTYC_KIC4, KEYC_IC|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
392 { TTYC_KIC5, KEYC_IC|KEYC_CTRL0x00200000000000ULL },
393 { TTYC_KIC6, KEYC_IC|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
394 { TTYC_KIC7, KEYC_IC|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
395 { TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT0x00400000000000ULL },
396 { TTYC_KLFT3, KEYC_LEFT|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
397 { TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
398 { TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL0x00200000000000ULL },
399 { TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
400 { TTYC_KLFT7, KEYC_LEFT|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
401 { TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT0x00400000000000ULL },
402 { TTYC_KNXT3, KEYC_NPAGE|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
403 { TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
404 { TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL0x00200000000000ULL },
405 { TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
406 { TTYC_KNXT7, KEYC_NPAGE|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
407 { TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT0x00400000000000ULL },
408 { TTYC_KPRV3, KEYC_PPAGE|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
409 { TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
410 { TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL0x00200000000000ULL },
411 { TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
412 { TTYC_KPRV7, KEYC_PPAGE|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
413 { TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT0x00400000000000ULL },
414 { TTYC_KRIT3, KEYC_RIGHT|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
415 { TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
416 { TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL0x00200000000000ULL },
417 { TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
418 { TTYC_KRIT7, KEYC_RIGHT|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
419 { TTYC_KRI, KEYC_UP|KEYC_SHIFT0x00400000000000ULL },
420 { TTYC_KUP2, KEYC_UP|KEYC_SHIFT0x00400000000000ULL },
421 { TTYC_KUP3, KEYC_UP|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
422 { TTYC_KUP4, KEYC_UP|KEYC_SHIFT0x00400000000000ULL|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL },
423 { TTYC_KUP5, KEYC_UP|KEYC_CTRL0x00200000000000ULL },
424 { TTYC_KUP6, KEYC_UP|KEYC_SHIFT0x00400000000000ULL|KEYC_CTRL0x00200000000000ULL },
425 { TTYC_KUP7, KEYC_UP|KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL|KEYC_CTRL0x00200000000000ULL },
426};
427
428/* Add key to tree. */
429static void
430tty_keys_add(struct tty *tty, const char *s, key_code key)
431{
432 struct tty_key *tk;
433 size_t size;
434 const char *keystr;
435
436 keystr = key_string_lookup_key(key, 1);
437 if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL((void *)0)) {
438 log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
439 tty_keys_add1(&tty->key_tree, s, key);
440 } else {
441 log_debug("replacing key %s: 0x%llx (%s)", s, key, keystr);
442 tk->key = key;
443 }
444}
445
446/* Add next node to the tree. */
447static void
448tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
449{
450 struct tty_key *tk;
451
452 /* Allocate a tree entry if there isn't one already. */
453 tk = *tkp;
454 if (tk == NULL((void *)0)) {
455 tk = *tkp = xcalloc(1, sizeof *tk);
456 tk->ch = *s;
457 tk->key = KEYC_UNKNOWN0x000fe000000000ULL;
458 }
459
460 /* Find the next entry. */
461 if (*s == tk->ch) {
462 /* Move forward in string. */
463 s++;
464
465 /* If this is the end of the string, no more is necessary. */
466 if (*s == '\0') {
467 tk->key = key;
468 return;
469 }
470
471 /* Use the child tree for the next character. */
472 tkp = &tk->next;
473 } else {
474 if (*s < tk->ch)
475 tkp = &tk->left;
476 else if (*s > tk->ch)
477 tkp = &tk->right;
478 }
479
480 /* And recurse to add it. */
481 tty_keys_add1(tkp, s, key);
482}
483
484/* Initialise a key tree from the table. */
485void
486tty_keys_build(struct tty *tty)
487{
488 const struct tty_default_key_raw *tdkr;
489 const struct tty_default_key_xterm *tdkx;
490 const struct tty_default_key_code *tdkc;
491 u_int i, j;
492 const char *s;
493 struct options_entry *o;
494 struct options_array_item *a;
495 union options_value *ov;
496 char copy[16];
497 key_code key;
498
499 if (tty->key_tree != NULL((void *)0))
500 tty_keys_free(tty);
501 tty->key_tree = NULL((void *)0);
502
503 for (i = 0; i < nitems(tty_default_xterm_keys)(sizeof((tty_default_xterm_keys)) / sizeof((tty_default_xterm_keys
)[0]))
; i++) {
504 tdkx = &tty_default_xterm_keys[i];
505 for (j = 2; j < nitems(tty_default_xterm_modifiers)(sizeof((tty_default_xterm_modifiers)) / sizeof((tty_default_xterm_modifiers
)[0]))
; j++) {
506 strlcpy(copy, tdkx->template, sizeof copy);
507 copy[strcspn(copy, "_")] = '0' + j;
508
509 key = tdkx->key|tty_default_xterm_modifiers[j];
510 tty_keys_add(tty, copy, key);
511 }
512 }
513 for (i = 0; i < nitems(tty_default_raw_keys)(sizeof((tty_default_raw_keys)) / sizeof((tty_default_raw_keys
)[0]))
; i++) {
514 tdkr = &tty_default_raw_keys[i];
515
516 s = tdkr->string;
517 if (*s != '\0')
518 tty_keys_add(tty, s, tdkr->key);
519 }
520 for (i = 0; i < nitems(tty_default_code_keys)(sizeof((tty_default_code_keys)) / sizeof((tty_default_code_keys
)[0]))
; i++) {
521 tdkc = &tty_default_code_keys[i];
522
523 s = tty_term_string(tty->term, tdkc->code);
524 if (*s != '\0')
525 tty_keys_add(tty, s, tdkc->key);
526
527 }
528
529 o = options_get(global_options, "user-keys");
530 if (o != NULL((void *)0)) {
531 a = options_array_first(o);
532 while (a != NULL((void *)0)) {
533 i = options_array_item_index(a);
534 ov = options_array_item_value(a);
535 tty_keys_add(tty, ov->string, KEYC_USER0x0000000010f000ULL + i);
536 a = options_array_next(a);
537 }
538 }
539}
540
541/* Free the entire key tree. */
542void
543tty_keys_free(struct tty *tty)
544{
545 tty_keys_free1(tty->key_tree);
546}
547
548/* Free a single key. */
549static void
550tty_keys_free1(struct tty_key *tk)
551{
552 if (tk->next != NULL((void *)0))
553 tty_keys_free1(tk->next);
554 if (tk->left != NULL((void *)0))
555 tty_keys_free1(tk->left);
556 if (tk->right != NULL((void *)0))
557 tty_keys_free1(tk->right);
558 free(tk);
559}
560
561/* Lookup a key in the tree. */
562static struct tty_key *
563tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size)
564{
565 *size = 0;
566 return (tty_keys_find1(tty->key_tree, buf, len, size));
567}
568
569/* Find the next node. */
570static struct tty_key *
571tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
572{
573 /* If no data, no match. */
574 if (len == 0)
575 return (NULL((void *)0));
576
577 /* If the node is NULL, this is the end of the tree. No match. */
578 if (tk == NULL((void *)0))
579 return (NULL((void *)0));
580
581 /* Pick the next in the sequence. */
582 if (tk->ch == *buf) {
583 /* Move forward in the string. */
584 buf++; len--;
585 (*size)++;
586
587 /* At the end of the string, return the current node. */
588 if (len == 0 || (tk->next == NULL((void *)0) && tk->key != KEYC_UNKNOWN0x000fe000000000ULL))
589 return (tk);
590
591 /* Move into the next tree for the following character. */
592 tk = tk->next;
593 } else {
594 if (*buf < tk->ch)
595 tk = tk->left;
596 else if (*buf > tk->ch)
597 tk = tk->right;
598 }
599
600 /* Move to the next in the tree. */
601 return (tty_keys_find1(tk, buf, len, size));
602}
603
604/* Look up part of the next key. */
605static int
606tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
607 size_t *size, int expired)
608{
609 struct client *c = tty->client;
610 struct tty_key *tk, *tk1;
611 struct utf8_data ud;
612 enum utf8_state more;
613 utf8_char uc;
614 u_int i;
615
616 log_debug("%s: next key is %zu (%.*s) (expired=%d)", c->name, len,
617 (int)len, buf, expired);
618
619 /* Is this a known key? */
620 tk = tty_keys_find(tty, buf, len, size);
621 if (tk != NULL((void *)0) && tk->key != KEYC_UNKNOWN0x000fe000000000ULL) {
622 tk1 = tk;
623 do
624 log_debug("%s: keys in list: %#llx", c->name, tk1->key);
625 while ((tk1 = tk1->next) != NULL((void *)0));
626 if (tk->next != NULL((void *)0) && !expired)
627 return (1);
628 *key = tk->key;
629 return (0);
630 }
631
632 /* Is this valid UTF-8? */
633 more = utf8_open(&ud, (u_char)*buf);
634 if (more == UTF8_MORE) {
635 *size = ud.size;
636 if (len < ud.size) {
637 if (!expired)
638 return (1);
639 return (-1);
640 }
641 for (i = 1; i < ud.size; i++)
642 more = utf8_append(&ud, (u_char)buf[i]);
643 if (more != UTF8_DONE)
644 return (-1);
645
646 if (utf8_from_data(&ud, &uc) != UTF8_DONE)
647 return (-1);
648 *key = uc;
649
650 log_debug("%s: UTF-8 key %.*s %#llx", c->name, (int)ud.size,
651 ud.data, *key);
652 return (0);
653 }
654
655 return (-1);
656}
657
658/* Process at least one key in the buffer. Return 0 if no keys present. */
659int
660tty_keys_next(struct tty *tty)
661{
662 struct client *c = tty->client;
663 struct timeval tv;
664 const char *buf;
665 size_t len, size;
666 cc_t bspace;
667 int delay, expired = 0, n;
668 key_code key;
669 struct mouse_event m = { 0 };
670 struct key_event *event;
671
672 /* Get key buffer. */
673 buf = EVBUFFER_DATA(tty->in)(tty->in)->buffer;
674 len = EVBUFFER_LENGTH(tty->in)(tty->in)->off;
675 if (len == 0)
4
Assuming 'len' is not equal to 0
5
Taking false branch
676 return (0);
677 log_debug("%s: keys are %zu (%.*s)", c->name, len, (int)len, buf);
678
679 /* Is this a clipboard response? */
680 switch (tty_keys_clipboard(tty, buf, len, &size)) {
6
Control jumps to 'case -1:' at line 684
681 case 0: /* yes */
682 key = KEYC_UNKNOWN0x000fe000000000ULL;
683 goto complete_key;
684 case -1: /* no, or not valid */
685 break;
686 case 1: /* partial */
687 goto partial_key;
688 }
689
690 /* Is this a primary device attributes response? */
691 switch (tty_keys_device_attributes(tty, buf, len, &size)) {
7
Execution continues on line 691
8
Control jumps to 'case -1:' at line 695
692 case 0: /* yes */
693 key = KEYC_UNKNOWN0x000fe000000000ULL;
694 goto complete_key;
695 case -1: /* no, or not valid */
696 break;
697 case 1: /* partial */
698 goto partial_key;
699 }
700
701 /* Is this a secondary device attributes response? */
702 switch (tty_keys_device_attributes2(tty, buf, len, &size)) {
9
Execution continues on line 702
10
Control jumps to 'case -1:' at line 706
703 case 0: /* yes */
704 key = KEYC_UNKNOWN0x000fe000000000ULL;
705 goto complete_key;
706 case -1: /* no, or not valid */
707 break;
708 case 1: /* partial */
709 goto partial_key;
710 }
711
712 /* Is this an extended device attributes response? */
713 switch (tty_keys_extended_device_attributes(tty, buf, len, &size)) {
11
Execution continues on line 713
714 case 0: /* yes */
715 key = KEYC_UNKNOWN0x000fe000000000ULL;
716 goto complete_key;
717 case -1: /* no, or not valid */
718 break;
719 case 1: /* partial */
720 goto partial_key;
721 }
722
723 /* Is this a colours response? */
724 switch (tty_keys_colours(tty, buf, len, &size)) {
12
'Default' branch taken. Execution continues on line 724
13
Calling 'tty_keys_colours'
725 case 0: /* yes */
726 key = KEYC_UNKNOWN0x000fe000000000ULL;
727 goto complete_key;
728 case -1: /* no, or not valid */
729 break;
730 case 1: /* partial */
731 goto partial_key;
732 }
733
734 /* Is this a mouse key press? */
735 switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
736 case 0: /* yes */
737 key = KEYC_MOUSE;
738 goto complete_key;
739 case -1: /* no, or not valid */
740 break;
741 case -2: /* yes, but we don't care. */
742 key = KEYC_MOUSE;
743 goto discard_key;
744 case 1: /* partial */
745 goto partial_key;
746 }
747
748 /* Is this an extended key press? */
749 switch (tty_keys_extended_key(tty, buf, len, &size, &key)) {
750 case 0: /* yes */
751 goto complete_key;
752 case -1: /* no, or not valid */
753 break;
754 case 1: /* partial */
755 goto partial_key;
756 }
757
758first_key:
759 /* Try to lookup complete key. */
760 n = tty_keys_next1(tty, buf, len, &key, &size, expired);
761 if (n == 0) /* found */
762 goto complete_key;
763 if (n == 1)
764 goto partial_key;
765
766 /*
767 * If not a complete key, look for key with an escape prefix (meta
768 * modifier).
769 */
770 if (*buf == '\033' && len > 1) {
771 /* Look for a key without the escape. */
772 n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired);
773 if (n == 0) { /* found */
774 if (key & KEYC_IMPLIED_META0x08000000000000ULL) {
775 /*
776 * We want the escape key as well as the xterm
777 * key, because the xterm sequence implicitly
778 * includes the escape (so if we see
779 * \033\033[1;3D we know it is an Escape
780 * followed by M-Left, not just M-Left).
781 */
782 key = '\033';
783 size = 1;
784 goto complete_key;
785 }
786 key |= KEYC_META0x00100000000000ULL;
787 size++;
788 goto complete_key;
789 }
790 if (n == 1) /* partial */
791 goto partial_key;
792 }
793
794 /*
795 * At this point, we know the key is not partial (with or without
796 * escape). So pass it through even if the timer has not expired.
797 */
798 if (*buf == '\033' && len >= 2) {
799 key = (u_char)buf[1] | KEYC_META0x00100000000000ULL;
800 size = 2;
801 } else {
802 key = (u_char)buf[0];
803 size = 1;
804 }
805 goto complete_key;
806
807partial_key:
808 log_debug("%s: partial key %.*s", c->name, (int)len, buf);
809
810 /* If timer is going, check for expiration. */
811 if (tty->flags & TTY_TIMER0x4) {
812 if (evtimer_initialized(&tty->key_timer)((&tty->key_timer)->ev_flags & 0x80) &&
813 !evtimer_pending(&tty->key_timer, NULL)event_pending(&tty->key_timer, 0x01, ((void *)0))) {
814 expired = 1;
815 goto first_key;
816 }
817 return (0);
818 }
819
820 /* Get the time period. */
821 delay = options_get_number(global_options, "escape-time");
822 if (delay == 0)
823 delay = 1;
824 tv.tv_sec = delay / 1000;
825 tv.tv_usec = (delay % 1000) * 1000L;
826
827 /* Start the timer. */
828 if (event_initialized(&tty->key_timer)((&tty->key_timer)->ev_flags & 0x80))
829 evtimer_del(&tty->key_timer)event_del(&tty->key_timer);
830 evtimer_set(&tty->key_timer, tty_keys_callback, tty)event_set(&tty->key_timer, -1, 0, tty_keys_callback, tty
)
;
831 evtimer_add(&tty->key_timer, &tv)event_add(&tty->key_timer, &tv);
832
833 tty->flags |= TTY_TIMER0x4;
834 return (0);
835
836complete_key:
837 log_debug("%s: complete key %.*s %#llx", c->name, (int)size, buf, key);
838
839 /*
840 * Check for backspace key using termios VERASE - the terminfo
841 * kbs entry is extremely unreliable, so cannot be safely
842 * used. termios should have a better idea.
843 */
844 bspace = tty->tio.c_cc[VERASE3];
845 if (bspace != _POSIX_VDISABLE(0377) && (key & KEYC_MASK_KEY0x000fffffffffffULL) == bspace)
846 key = (key & KEYC_MASK_MODIFIERS0x00f00000000000ULL)|KEYC_BSPACE;
847
848 /* Remove data from buffer. */
849 evbuffer_drain(tty->in, size);
850
851 /* Remove key timer. */
852 if (event_initialized(&tty->key_timer)((&tty->key_timer)->ev_flags & 0x80))
853 evtimer_del(&tty->key_timer)event_del(&tty->key_timer);
854 tty->flags &= ~TTY_TIMER0x4;
855
856 /* Check for focus events. */
857 if (key == KEYC_FOCUS_OUT) {
858 c->flags &= ~CLIENT_FOCUSED0x8000;
859 window_update_focus(c->session->curw->window);
860 notify_client("client-focus-out", c);
861 } else if (key == KEYC_FOCUS_IN) {
862 c->flags |= CLIENT_FOCUSED0x8000;
863 notify_client("client-focus-in", c);
864 window_update_focus(c->session->curw->window);
865 }
866
867 /* Fire the key. */
868 if (key != KEYC_UNKNOWN0x000fe000000000ULL) {
869 event = xmalloc(sizeof *event);
870 event->key = key;
871 memcpy(&event->m, &m, sizeof event->m);
872 if (!server_client_handle_key(c, event))
873 free(event);
874 }
875
876 return (1);
877
878discard_key:
879 log_debug("%s: discard key %.*s %#llx", c->name, (int)size, buf, key);
880
881 /* Remove data from buffer. */
882 evbuffer_drain(tty->in, size);
883
884 return (1);
885}
886
887/* Key timer callback. */
888static void
889tty_keys_callback(__unused__attribute__((__unused__)) int fd, __unused__attribute__((__unused__)) short events, void *data)
890{
891 struct tty *tty = data;
892
893 if (tty->flags & TTY_TIMER0x4) {
1
Assuming the condition is true
2
Taking true branch
894 while (tty_keys_next(tty))
3
Calling 'tty_keys_next'
895 ;
896 }
897}
898
899/*
900 * Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu,
901 * where k is key as a number and m is a modifier. Returns 0 for success, -1
902 * for failure, 1 for partial;
903 */
904static int
905tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
906 size_t *size, key_code *key)
907{
908 struct client *c = tty->client;
909 size_t end;
910 u_int number, modifiers;
911 char tmp[64];
912 cc_t bspace;
913 key_code nkey;
914 key_code onlykey;
915
916 *size = 0;
917
918 /* First two bytes are always \033[. */
919 if (buf[0] != '\033')
920 return (-1);
921 if (len == 1)
922 return (1);
923 if (buf[1] != '[')
924 return (-1);
925 if (len == 2)
926 return (1);
927
928 /*
929 * Look for a terminator. Stop at either '~' or anything that isn't a
930 * number or ';'.
931 */
932 for (end = 2; end < len && end != sizeof tmp; end++) {
933 if (buf[end] == '~')
934 break;
935 if (!isdigit((u_char)buf[end]) && buf[end] != ';')
936 break;
937 }
938 if (end == len)
939 return (1);
940 if (end == sizeof tmp || (buf[end] != '~' && buf[end] != 'u'))
941 return (-1);
942
943 /* Copy to the buffer. */
944 memcpy(tmp, buf + 2, end);
945 tmp[end] = '\0';
946
947 /* Try to parse either form of key. */
948 if (buf[end] == '~') {
949 if (sscanf(tmp, "27;%u;%u", &modifiers, &number) != 2)
950 return (-1);
951 } else {
952 if (sscanf(tmp ,"%u;%u", &number, &modifiers) != 2)
953 return (-1);
954 }
955 *size = end + 1;
956
957 /* Store the key. */
958 bspace = tty->tio.c_cc[VERASE3];
959 if (bspace != _POSIX_VDISABLE(0377) && number == bspace)
960 nkey = KEYC_BSPACE;
961 else
962 nkey = number;
963
964 /* Update the modifiers. */
965 if (modifiers > 0) {
966 modifiers--;
967 if (modifiers & 1)
968 nkey |= KEYC_SHIFT0x00400000000000ULL;
969 if (modifiers & 2)
970 nkey |= (KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL); /* Alt */
971 if (modifiers & 4)
972 nkey |= KEYC_CTRL0x00200000000000ULL;
973 if (modifiers & 8)
974 nkey |= (KEYC_META0x00100000000000ULL|KEYC_IMPLIED_META0x08000000000000ULL); /* Meta */
975 }
976
977 /*
978 * Don't allow both KEYC_CTRL and as an implied modifier. Also convert
979 * C-X into C-x and so on.
980 */
981 if (nkey & KEYC_CTRL0x00200000000000ULL) {
982 onlykey = (nkey & KEYC_MASK_KEY0x000fffffffffffULL);
983 if (onlykey < 32 &&
984 onlykey != 9 &&
985 onlykey != 13 &&
986 onlykey != 27)
987 /* nothing */;
988 else if (onlykey >= 97 && onlykey <= 122)
989 onlykey -= 96;
990 else if (onlykey >= 64 && onlykey <= 95)
991 onlykey -= 64;
992 else if (onlykey == 32)
993 onlykey = 0;
994 else if (onlykey == 63)
995 onlykey = 127;
996 else
997 onlykey |= KEYC_CTRL0x00200000000000ULL;
998 nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS0x00f00000000000ULL) & ~KEYC_CTRL0x00200000000000ULL);
999 }
1000
1001 if (log_get_level() != 0) {
1002 log_debug("%s: extended key %.*s is %llx (%s)", c->name,
1003 (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
1004 }
1005 *key = nkey;
1006 return (0);
1007}
1008
1009/*
1010 * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
1011 * (probably a mouse sequence but need more data), -2 if an invalid mouse
1012 * sequence.
1013 */
1014static int
1015tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
1016 struct mouse_event *m)
1017{
1018 struct client *c = tty->client;
1019 u_int i, x, y, b, sgr_b;
1020 u_char sgr_type, ch;
1021
1022 /*
1023 * Standard mouse sequences are \033[M followed by three characters
1024 * indicating button, X and Y, all based at 32 with 1,1 top-left.
1025 *
1026 * UTF-8 mouse sequences are similar but the three are expressed as
1027 * UTF-8 characters.
1028 *
1029 * SGR extended mouse sequences are \033[< followed by three numbers in
1030 * decimal and separated by semicolons indicating button, X and Y. A
1031 * trailing 'M' is click or scroll and trailing 'm' release. All are
1032 * based at 0 with 1,1 top-left.
1033 */
1034
1035 *size = 0;
1036 x = y = b = sgr_b = 0;
1037 sgr_type = ' ';
1038
1039 /* First two bytes are always \033[. */
1040 if (buf[0] != '\033')
1041 return (-1);
1042 if (len == 1)
1043 return (1);
1044 if (buf[1] != '[')
1045 return (-1);
1046 if (len == 2)
1047 return (1);
1048
1049 /*
1050 * Third byte is M in old standard (and UTF-8 extension which we do not
1051 * support), < in SGR extension.
1052 */
1053 if (buf[2] == 'M') {
1054 /* Read the three inputs. */
1055 *size = 3;
1056 for (i = 0; i < 3; i++) {
1057 if (len <= *size)
1058 return (1);
1059 ch = (u_char)buf[(*size)++];
1060 if (i == 0)
1061 b = ch;
1062 else if (i == 1)
1063 x = ch;
1064 else
1065 y = ch;
1066 }
1067 log_debug("%s: mouse input: %.*s", c->name, (int)*size, buf);
1068
1069 /* Check and return the mouse input. */
1070 if (b < MOUSE_PARAM_BTN_OFF0x20 ||
1071 x < MOUSE_PARAM_POS_OFF0x21 ||
1072 y < MOUSE_PARAM_POS_OFF0x21)
1073 return (-2);
1074 b -= MOUSE_PARAM_BTN_OFF0x20;
1075 x -= MOUSE_PARAM_POS_OFF0x21;
1076 y -= MOUSE_PARAM_POS_OFF0x21;
1077 } else if (buf[2] == '<') {
1078 /* Read the three inputs. */
1079 *size = 3;
1080 while (1) {
1081 if (len <= *size)
1082 return (1);
1083 ch = (u_char)buf[(*size)++];
1084 if (ch == ';')
1085 break;
1086 if (ch < '0' || ch > '9')
1087 return (-1);
1088 sgr_b = 10 * sgr_b + (ch - '0');
1089 }
1090 while (1) {
1091 if (len <= *size)
1092 return (1);
1093 ch = (u_char)buf[(*size)++];
1094 if (ch == ';')
1095 break;
1096 if (ch < '0' || ch > '9')
1097 return (-1);
1098 x = 10 * x + (ch - '0');
1099 }
1100 while (1) {
1101 if (len <= *size)
1102 return (1);
1103 ch = (u_char)buf[(*size)++];
1104 if (ch == 'M' || ch == 'm')
1105 break;
1106 if (ch < '0' || ch > '9')
1107 return (-1);
1108 y = 10 * y + (ch - '0');
1109 }
1110 log_debug("%s: mouse input (SGR): %.*s", c->name, (int)*size,
1111 buf);
1112
1113 /* Check and return the mouse input. */
1114 if (x < 1 || y < 1)
1115 return (-2);
1116 x--;
1117 y--;
1118 b = sgr_b;
1119
1120 /* Type is M for press, m for release. */
1121 sgr_type = ch;
1122 if (sgr_type == 'm')
1123 b = 3;
1124
1125 /*
1126 * Some terminals (like PuTTY 0.63) mistakenly send
1127 * button-release events for scroll-wheel button-press event.
1128 * Discard it before it reaches any program running inside
1129 * tmux.
1130 */
1131 if (sgr_type == 'm' && MOUSE_WHEEL(sgr_b)(((sgr_b) & 195) == 64 || ((sgr_b) & 195) == 65))
1132 return (-2);
1133 } else
1134 return (-1);
1135
1136 /* Fill mouse event. */
1137 m->lx = tty->mouse_last_x;
1138 m->x = x;
1139 m->ly = tty->mouse_last_y;
1140 m->y = y;
1141 m->lb = tty->mouse_last_b;
1142 m->b = b;
1143 m->sgr_type = sgr_type;
1144 m->sgr_b = sgr_b;
1145
1146 /* Update last mouse state. */
1147 tty->mouse_last_x = x;
1148 tty->mouse_last_y = y;
1149 tty->mouse_last_b = b;
1150
1151 return (0);
1152}
1153
1154/*
1155 * Handle OSC 52 clipboard input. Returns 0 for success, -1 for failure, 1 for
1156 * partial.
1157 */
1158static int
1159tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
1160{
1161 struct client *c = tty->client;
1162 struct window_pane *wp;
1163 size_t end, terminator = 0, needed;
1164 char *copy, *out;
1165 int outlen;
1166 u_int i;
1167
1168 *size = 0;
1169
1170 /* First five bytes are always \033]52;. */
1171 if (buf[0] != '\033')
1172 return (-1);
1173 if (len == 1)
1174 return (1);
1175 if (buf[1] != ']')
1176 return (-1);
1177 if (len == 2)
1178 return (1);
1179 if (buf[2] != '5')
1180 return (-1);
1181 if (len == 3)
1182 return (1);
1183 if (buf[3] != '2')
1184 return (-1);
1185 if (len == 4)
1186 return (1);
1187 if (buf[4] != ';')
1188 return (-1);
1189 if (len == 5)
1190 return (1);
1191
1192 /* Find the terminator if any. */
1193 for (end = 5; end < len; end++) {
1194 if (buf[end] == '\007') {
1195 terminator = 1;
1196 break;
1197 }
1198 if (end > 5 && buf[end - 1] == '\033' && buf[end] == '\\') {
1199 terminator = 2;
1200 break;
1201 }
1202 }
1203 if (end == len)
1204 return (1);
1205 *size = end + terminator;
1206
1207 /* Skip the initial part. */
1208 buf += 5;
1209 end -= 5;
1210
1211 /* Adjust end so that it points to the start of the terminator. */
1212 end -= terminator - 1;
1213
1214 /* Get the second argument. */
1215 while (end != 0 && *buf != ';') {
1216 buf++;
1217 end--;
1218 }
1219 if (end == 0 || end == 1)
1220 return (0);
1221 buf++;
1222 end--;
1223
1224 /* If we did not request this, ignore it. */
1225 if (~tty->flags & TTY_OSC52QUERY0x40)
1226 return (0);
1227 tty->flags &= ~TTY_OSC52QUERY0x40;
1228 evtimer_del(&tty->clipboard_timer)event_del(&tty->clipboard_timer);
1229
1230 /* It has to be a string so copy it. */
1231 copy = xmalloc(end + 1);
1232 memcpy(copy, buf, end);
1233 copy[end] = '\0';
1234
1235 /* Convert from base64. */
1236 needed = (end / 4) * 3;
1237 out = xmalloc(needed);
1238 if ((outlen = b64_pton__b64_pton(copy, out, len)) == -1) {
1239 free(out);
1240 free(copy);
1241 return (0);
1242 }
1243 free(copy);
1244
1245 /* Create a new paste buffer and forward to panes. */
1246 log_debug("%s: %.*s", __func__, outlen, out);
1247 if (c->flags & CLIENT_CLIPBOARDBUFFER0x800000000ULL) {
1248 paste_add(NULL((void *)0), out, outlen);
1249 c->flags &= ~CLIENT_CLIPBOARDBUFFER0x800000000ULL;
1250 }
1251 for (i = 0; i < c->clipboard_npanes; i++) {
1252 wp = window_pane_find_by_id(c->clipboard_panes[i]);
1253 if (wp != NULL((void *)0))
1254 input_reply_clipboard(wp->event, out, outlen, "\033\\");
1255 }
1256 free(c->clipboard_panes);
1257 c->clipboard_panes = NULL((void *)0);
1258 c->clipboard_npanes = 0;
1259
1260 return (0);
1261}
1262
1263/*
1264 * Handle primary device attributes input. Returns 0 for success, -1 for
1265 * failure, 1 for partial.
1266 */
1267static int
1268tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
1269 size_t *size)
1270{
1271 struct client *c = tty->client;
1272 int *features = &c->term_features;
1273 u_int i, n = 0;
1274 char tmp[128], *endptr, p[32] = { 0 }, *cp, *next;
1275
1276 *size = 0;
1277 if (tty->flags & TTY_HAVEDA0x100)
1278 return (-1);
1279
1280 /* First three bytes are always \033[?. */
1281 if (buf[0] != '\033')
1282 return (-1);
1283 if (len == 1)
1284 return (1);
1285 if (buf[1] != '[')
1286 return (-1);
1287 if (len == 2)
1288 return (1);
1289 if (buf[2] != '?')
1290 return (-1);
1291 if (len == 3)
1292 return (1);
1293
1294 /* Copy the rest up to a c. */
1295 for (i = 0; i < (sizeof tmp); i++) {
1296 if (3 + i == len)
1297 return (1);
1298 if (buf[3 + i] == 'c')
1299 break;
1300 tmp[i] = buf[3 + i];
1301 }
1302 if (i == (sizeof tmp))
1303 return (-1);
1304 tmp[i] = '\0';
1305 *size = 4 + i;
1306
1307 /* Convert all arguments to numbers. */
1308 cp = tmp;
1309 while ((next = strsep(&cp, ";")) != NULL((void *)0)) {
1310 p[n] = strtoul(next, &endptr, 10);
1311 if (*endptr != '\0')
1312 p[n] = 0;
1313 if (++n == nitems(p)(sizeof((p)) / sizeof((p)[0])))
1314 break;
1315 }
1316
1317 /*
1318 * Add terminal features. Hardware level 5 does not offer SIXEL but
1319 * some terminal emulators report it anyway and it does not harm
1320 * to check it here.
1321 *
1322 * DECSLRM and DECFRA should be supported by level 5 as well as level
1323 * 4, but VTE has rather ruined it by advertising level 5 despite not
1324 * supporting them.
1325 */
1326 switch (p[0]) {
1327 case 64: /* level 4 */
1328 tty_add_features(features, "margins,rectfill", ",");
1329 /* FALLTHROUGH */
1330 case 62: /* level 2 */
1331 case 63: /* level 3 */
1332 case 65: /* level 5 */
1333 for (i = 1; i < n; i++) {
1334 log_debug("%s: DA feature: %d", c->name, p[i]);
1335 if (p[i] == 4)
1336 tty_add_features(features, "sixel", ",");
1337 }
1338 break;
1339 }
1340 log_debug("%s: received primary DA %.*s", c->name, (int)*size, buf);
1341
1342 tty_update_features(tty);
1343 tty->flags |= TTY_HAVEDA0x100;
1344
1345 return (0);
1346}
1347
1348/*
1349 * Handle secondary device attributes input. Returns 0 for success, -1 for
1350 * failure, 1 for partial.
1351 */
1352static int
1353tty_keys_device_attributes2(struct tty *tty, const char *buf, size_t len,
1354 size_t *size)
1355{
1356 struct client *c = tty->client;
1357 int *features = &c->term_features;
1358 u_int i, n = 0;
1359 char tmp[128], *endptr, p[32] = { 0 }, *cp, *next;
1360
1361 *size = 0;
1362 if (tty->flags & TTY_HAVEDA20x800)
1363 return (-1);
1364
1365 /* First three bytes are always \033[>. */
1366 if (buf[0] != '\033')
1367 return (-1);
1368 if (len == 1)
1369 return (1);
1370 if (buf[1] != '[')
1371 return (-1);
1372 if (len == 2)
1373 return (1);
1374 if (buf[2] != '>')
1375 return (-1);
1376 if (len == 3)
1377 return (1);
1378
1379 /* Copy the rest up to a c. */
1380 for (i = 0; i < (sizeof tmp); i++) {
1381 if (3 + i == len)
1382 return (1);
1383 if (buf[3 + i] == 'c')
1384 break;
1385 tmp[i] = buf[3 + i];
1386 }
1387 if (i == (sizeof tmp))
1388 return (-1);
1389 tmp[i] = '\0';
1390 *size = 4 + i;
1391
1392 /* Convert all arguments to numbers. */
1393 cp = tmp;
1394 while ((next = strsep(&cp, ";")) != NULL((void *)0)) {
1395 p[n] = strtoul(next, &endptr, 10);
1396 if (*endptr != '\0')
1397 p[n] = 0;
1398 if (++n == nitems(p)(sizeof((p)) / sizeof((p)[0])))
1399 break;
1400 }
1401
1402 /*
1403 * Add terminal features. We add DECSLRM and DECFRA for some
1404 * identification codes here, notably 64 will catch VT520, even though
1405 * we can't use level 5 from DA because of VTE.
1406 */
1407 switch (p[0]) {
1408 case 41: /* VT420 */
1409 case 61: /* VT510 */
1410 case 64: /* VT520 */
1411 tty_add_features(features, "margins,rectfill", ",");
1412 break;
1413 case 'M': /* mintty */
1414 tty_default_features(features, "mintty", 0);
1415 break;
1416 case 'T': /* tmux */
1417 tty_default_features(features, "tmux", 0);
1418 break;
1419 case 'U': /* rxvt-unicode */
1420 tty_default_features(features, "rxvt-unicode", 0);
1421 break;
1422 }
1423 log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf);
1424
1425 tty_update_features(tty);
1426 tty->flags |= TTY_HAVEDA20x800;
1427
1428 return (0);
1429}
1430
1431/*
1432 * Handle extended device attributes input. Returns 0 for success, -1 for
1433 * failure, 1 for partial.
1434 */
1435static int
1436tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
1437 size_t len, size_t *size)
1438{
1439 struct client *c = tty->client;
1440 int *features = &c->term_features;
1441 u_int i;
1442 char tmp[128];
1443
1444 *size = 0;
1445 if (tty->flags & TTY_HAVEXDA0x200)
1446 return (-1);
1447
1448 /* First four bytes are always \033P>|. */
1449 if (buf[0] != '\033')
1450 return (-1);
1451 if (len == 1)
1452 return (1);
1453 if (buf[1] != 'P')
1454 return (-1);
1455 if (len == 2)
1456 return (1);
1457 if (buf[2] != '>')
1458 return (-1);
1459 if (len == 3)
1460 return (1);
1461 if (buf[3] != '|')
1462 return (-1);
1463 if (len == 4)
1464 return (1);
1465
1466 /* Copy the rest up to \033\. */
1467 for (i = 0; i < (sizeof tmp) - 1; i++) {
1468 if (4 + i == len)
1469 return (1);
1470 if (buf[4 + i - 1] == '\033' && buf[4 + i] == '\\')
1471 break;
1472 tmp[i] = buf[4 + i];
1473 }
1474 if (i == (sizeof tmp) - 1)
1475 return (-1);
1476 tmp[i - 1] = '\0';
1477 *size = 5 + i;
1478
1479 /* Add terminal features. */
1480 if (strncmp(tmp, "iTerm2 ", 7) == 0)
1481 tty_default_features(features, "iTerm2", 0);
1482 else if (strncmp(tmp, "tmux ", 5) == 0)
1483 tty_default_features(features, "tmux", 0);
1484 else if (strncmp(tmp, "XTerm(", 6) == 0)
1485 tty_default_features(features, "XTerm", 0);
1486 else if (strncmp(tmp, "mintty ", 7) == 0)
1487 tty_default_features(features, "mintty", 0);
1488 log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);
1489
1490 free(c->term_type);
1491 c->term_type = xstrdup(tmp);
1492
1493 tty_update_features(tty);
1494 tty->flags |= TTY_HAVEXDA0x200;
1495
1496 return (0);
1497}
1498
1499/*
1500 * Handle foreground or background input. Returns 0 for success, -1 for
1501 * failure, 1 for partial.
1502 */
1503static int
1504tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size)
1505{
1506 struct client *c = tty->client;
1507 u_int i;
1508 char tmp[128];
1509 int n;
1510
1511 *size = 0;
1512
1513 /* First four bytes are always \033]1 and 0 or 1 and ;. */
1514 if (buf[0] != '\033')
14
Assuming the condition is false
15
Taking false branch
1515 return (-1);
1516 if (len
15.1
'len' is not equal to 1
== 1)
16
Taking false branch
1517 return (1);
1518 if (buf[1] != ']')
17
Assuming the condition is false
18
Taking false branch
1519 return (-1);
1520 if (len
18.1
'len' is not equal to 2
== 2)
19
Taking false branch
1521 return (1);
1522 if (buf[2] != '1')
20
Assuming the condition is false
21
Taking false branch
1523 return (-1);
1524 if (len
21.1
'len' is not equal to 3
== 3)
1525 return (1);
1526 if (buf[3] != '0' && buf[3] != '1')
22
Assuming the condition is false
1527 return (-1);
1528 if (len == 4)
23
Assuming 'len' is not equal to 4
24
Taking false branch
1529 return (1);
1530 if (buf[4] != ';')
25
Assuming the condition is false
26
Taking false branch
1531 return (-1);
1532 if (len == 5)
27
Assuming 'len' is not equal to 5
28
Taking false branch
1533 return (1);
1534
1535 /* Copy the rest up to \033\ or \007. */
1536 for (i = 0; i < (sizeof tmp) - 1; i++) {
29
Loop condition is true. Entering loop body
1537 if (5 + i == len)
1538 return (1);
1539 if (buf[5 + i - 1] == '\033' && buf[5 + i] == '\\')
1540 break;
1541 if (buf[5 + i] == '\007')
30
Assuming the condition is true
31
Taking true branch
1542 break;
1543 tmp[i] = buf[5 + i];
1544 }
1545 if (i == (sizeof tmp) - 1)
33
Taking false branch
1546 return (-1);
1547 if (tmp[i - 1] == '\033')
32
Execution continues on line 1545
34
The left operand of '==' is a garbage value due to array index out of bounds
1548 tmp[i - 1] = '\0';
1549 else
1550 tmp[i] = '\0';
1551 *size = 6 + i;
1552
1553 n = colour_parseX11(tmp);
1554 if (n != -1 && buf[3] == '0') {
1555 log_debug("%s: foreground is %s", c->name, colour_tostring(n));
1556 tty->fg = n;
1557 } else if (n != -1) {
1558 log_debug("%s: background is %s", c->name, colour_tostring(n));
1559 tty->bg = n;
1560 }
1561
1562 return (0);
1563}