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