1 #include "tmate.h"
2 #include "tmate-protocol.h"
3 
handle_notify(__unused struct tmate_session * session,struct tmate_unpacker * uk)4 static void handle_notify(__unused struct tmate_session *session,
5 			  struct tmate_unpacker *uk)
6 {
7 	char *msg = unpack_string(uk);
8 	tmate_status_message("%s", msg);
9 	free(msg);
10 }
11 
handle_legacy_pane_key(__unused struct tmate_session * _session,struct tmate_unpacker * uk)12 static void handle_legacy_pane_key(__unused struct tmate_session *_session,
13 				   struct tmate_unpacker *uk)
14 {
15 	struct session *s;
16 	struct window *w;
17 	struct window_pane *wp;
18 
19 	int key = unpack_int(uk);
20 
21 	s = RB_MIN(sessions, &sessions);
22 	if (!s)
23 		return;
24 
25 	w = s->curw->window;
26 	if (!w)
27 		return;
28 
29 	wp = w->active;
30 	if (!wp)
31 		return;
32 
33 	window_pane_key(wp, NULL, s, key, NULL);
34 }
35 
find_window_pane(struct session * s,int pane_id)36 static struct window_pane *find_window_pane(struct session *s, int pane_id)
37 {
38 	struct window *w;
39 
40 	if (pane_id != -1)
41 		return window_pane_find_by_id(pane_id);
42 
43 	w = s->curw->window;
44 	if (!w)
45 		return NULL;
46 
47 	return w->active;
48 }
49 
handle_pane_key(__unused struct tmate_session * _session,struct tmate_unpacker * uk)50 static void handle_pane_key(__unused struct tmate_session *_session,
51 			    struct tmate_unpacker *uk)
52 {
53 	struct session *s;
54 	struct window_pane *wp;
55 
56 	int pane_id = unpack_int(uk);
57 	key_code key = unpack_int(uk);
58 
59 	s = RB_MIN(sessions, &sessions);
60 	if (!s)
61 		return;
62 
63 	wp = find_window_pane(s, pane_id);
64 	if (!wp)
65 		return;
66 
67 	window_pane_key(wp, NULL, s, key, NULL);
68 }
69 
handle_resize(struct tmate_session * session,struct tmate_unpacker * uk)70 static void handle_resize(struct tmate_session *session,
71 			  struct tmate_unpacker *uk)
72 {
73 	session->min_sx = unpack_int(uk);
74 	session->min_sy = unpack_int(uk);
75 	recalculate_sizes();
76 }
77 
78 extern char		**cfg_causes;
79 extern u_int		  cfg_ncauses;
80 
handle_exec_cmd_str(__unused struct tmate_session * session,struct tmate_unpacker * uk)81 static void handle_exec_cmd_str(__unused struct tmate_session *session,
82 				struct tmate_unpacker *uk)
83 {
84 	struct cmd_q *cmd_q;
85 	struct cmd_list *cmdlist;
86 	char *cause;
87 	u_int i;
88 
89 	int client_id = unpack_int(uk);
90 	char *cmd_str = unpack_string(uk);
91 
92 	if (cmd_string_parse(cmd_str, &cmdlist, NULL, 0, &cause) != 0) {
93 		tmate_failed_cmd(client_id, cause);
94 		free(cause);
95 		goto out;
96 	}
97 
98 	cmd_q = cmdq_new(NULL);
99 	cmdq_run(cmd_q, cmdlist, NULL);
100 	cmd_list_free(cmdlist);
101 	cmdq_free(cmd_q);
102 
103 	/* error messages land in cfg_causes */
104 	for (i = 0; i < cfg_ncauses; i++) {
105 		tmate_failed_cmd(client_id, cfg_causes[i]);
106 		free(cfg_causes[i]);
107 	}
108 
109 	free(cfg_causes);
110 	cfg_causes = NULL;
111 	cfg_ncauses = 0;
112 
113 out:
114 	free(cmd_str);
115 }
116 
handle_exec_cmd(__unused struct tmate_session * session,struct tmate_unpacker * uk)117 static void handle_exec_cmd(__unused struct tmate_session *session,
118 			    struct tmate_unpacker *uk)
119 {
120 	struct cmd_q *cmd_q;
121 	struct cmd_list *cmdlist;
122 	struct cmd *cmd;
123 	char *cause;
124 	u_int i;
125 	unsigned int argc;
126 	char **argv;
127 
128 	int client_id = unpack_int(uk);
129 
130 	argc = uk->argc;
131 	argv = xmalloc(sizeof(char *) * argc);
132 	for (i = 0; i < argc; i++)
133 		argv[i] = unpack_string(uk);
134 
135 	cmd = cmd_parse(argc, argv, NULL, 0, &cause);
136 	if (!cmd) {
137 		tmate_failed_cmd(client_id, cause);
138 		free(cause);
139 		goto out;
140 	}
141 
142 	cmdlist = xcalloc(1, sizeof *cmdlist);
143 	cmdlist->references = 1;
144 	TAILQ_INIT(&cmdlist->list);
145 	TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
146 
147 	cmd_q = cmdq_new(NULL);
148 	cmdq_run(cmd_q, cmdlist, NULL);
149 	cmd_list_free(cmdlist);
150 	cmdq_free(cmd_q);
151 
152 	/* error messages land in cfg_causes */
153 	for (i = 0; i < cfg_ncauses; i++) {
154 		tmate_failed_cmd(client_id, cfg_causes[i]);
155 		free(cfg_causes[i]);
156 	}
157 
158 	free(cfg_causes);
159 	cfg_causes = NULL;
160 	cfg_ncauses = 0;
161 
162 out:
163 	cmd_free_argv(argc, argv);
164 }
165 
maybe_save_reconnection_data(struct tmate_session * session,const char * name,const char * value)166 static void maybe_save_reconnection_data(struct tmate_session *session,
167 				const char *name, const char *value)
168 {
169 	if (!strcmp(name, "tmate_reconnection_data")) {
170 		free(session->reconnection_data);
171 		session->reconnection_data = xstrdup(value);
172 	}
173 }
174 
handle_set_env(struct tmate_session * session,struct tmate_unpacker * uk)175 static void handle_set_env(struct tmate_session *session,
176 			   struct tmate_unpacker *uk)
177 {
178 	char *name = unpack_string(uk);
179 	char *value = unpack_string(uk);
180 
181 	tmate_set_env(name, value);
182 	maybe_save_reconnection_data(session, name, value);
183 
184 	free(name);
185 	free(value);
186 }
187 
handle_ready(struct tmate_session * session,__unused struct tmate_unpacker * uk)188 static void handle_ready(struct tmate_session *session,
189 			 __unused struct tmate_unpacker *uk)
190 {
191 	session->tmate_env_ready = 1;
192 	signal_waiting_clients("tmate-ready");
193 }
194 
tmate_dispatch_slave_message(struct tmate_session * session,struct tmate_unpacker * uk)195 void tmate_dispatch_slave_message(struct tmate_session *session,
196 				  struct tmate_unpacker *uk)
197 {
198 	int cmd = unpack_int(uk);
199 	switch (cmd) {
200 #define dispatch(c, f) case c: f(session, uk); break
201 	dispatch(TMATE_IN_NOTIFY,		handle_notify);
202 	dispatch(TMATE_IN_LEGACY_PANE_KEY,	handle_legacy_pane_key);
203 	dispatch(TMATE_IN_RESIZE,		handle_resize);
204 	dispatch(TMATE_IN_EXEC_CMD_STR,		handle_exec_cmd_str);
205 	dispatch(TMATE_IN_SET_ENV,		handle_set_env);
206 	dispatch(TMATE_IN_READY,		handle_ready);
207 	dispatch(TMATE_IN_PANE_KEY,		handle_pane_key);
208 	dispatch(TMATE_IN_EXEC_CMD,		handle_exec_cmd);
209 	default: tmate_info("Bad message type: %d", cmd);
210 	}
211 }
212