Annotation of src/usr.bin/tmux/server-msg.c, Revision 1.3
1.3 ! nicm 1: /* $OpenBSD: server-msg.c,v 1.2 2009/06/04 21:43:24 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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:
21: #include <errno.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <time.h>
25: #include <unistd.h>
26:
27: #include "tmux.h"
28:
29: int server_msg_fn_command(struct hdr *, struct client *);
30: int server_msg_fn_identify(struct hdr *, struct client *);
31: int server_msg_fn_resize(struct hdr *, struct client *);
32: int server_msg_fn_exiting(struct hdr *, struct client *);
33: int server_msg_fn_unlock(struct hdr *, struct client *);
34: int server_msg_fn_wakeup(struct hdr *, struct client *);
35:
36: void printflike2 server_msg_fn_command_error(
37: struct cmd_ctx *, const char *, ...);
38: void printflike2 server_msg_fn_command_print(
39: struct cmd_ctx *, const char *, ...);
40: void printflike2 server_msg_fn_command_info(
41: struct cmd_ctx *, const char *, ...);
42:
43: struct server_msg {
44: enum hdrtype type;
45: int (*fn)(struct hdr *, struct client *);
46: };
47: const struct server_msg server_msg_table[] = {
48: { MSG_IDENTIFY, server_msg_fn_identify },
49: { MSG_COMMAND, server_msg_fn_command },
50: { MSG_RESIZE, server_msg_fn_resize },
51: { MSG_EXITING, server_msg_fn_exiting },
52: { MSG_UNLOCK, server_msg_fn_unlock },
53: { MSG_WAKEUP, server_msg_fn_wakeup },
54: };
55:
56: int
57: server_msg_dispatch(struct client *c)
58: {
59: struct hdr hdr;
60: const struct server_msg *msg;
61: u_int i;
62: int n;
63:
64: for (;;) {
65: if (BUFFER_USED(c->in) < sizeof hdr)
66: return (0);
67: memcpy(&hdr, BUFFER_OUT(c->in), sizeof hdr);
68: if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size)
69: return (0);
70: buffer_remove(c->in, sizeof hdr);
71:
72: for (i = 0; i < nitems(server_msg_table); i++) {
73: msg = server_msg_table + i;
74: if (msg->type == hdr.type) {
75: if ((n = msg->fn(&hdr, c)) != 0)
76: return (n);
77: break;
78: }
79: }
80: if (i == nitems(server_msg_table))
81: fatalx("unexpected message");
82: }
83: }
84:
85: void printflike2
86: server_msg_fn_command_error(struct cmd_ctx *ctx, const char *fmt, ...)
87: {
88: va_list ap;
89: char *msg;
90:
91: va_start(ap, fmt);
92: xvasprintf(&msg, fmt, ap);
93: va_end(ap);
94:
95: server_write_client(ctx->cmdclient, MSG_ERROR, msg, strlen(msg));
96: xfree(msg);
97: }
98:
99: void printflike2
100: server_msg_fn_command_print(struct cmd_ctx *ctx, const char *fmt, ...)
101: {
102: va_list ap;
103: char *msg;
104:
105: va_start(ap, fmt);
106: xvasprintf(&msg, fmt, ap);
107: va_end(ap);
108:
109: server_write_client(ctx->cmdclient, MSG_PRINT, msg, strlen(msg));
110: xfree(msg);
111: }
112:
113: void printflike2
114: server_msg_fn_command_info(struct cmd_ctx *ctx, const char *fmt, ...)
115: {
116: va_list ap;
117: char *msg;
118:
119: if (be_quiet)
120: return;
121:
122: va_start(ap, fmt);
123: xvasprintf(&msg, fmt, ap);
124: va_end(ap);
125:
126: server_write_client(ctx->cmdclient, MSG_PRINT, msg, strlen(msg));
127: xfree(msg);
128: }
129:
130: int
131: server_msg_fn_command(struct hdr *hdr, struct client *c)
132: {
133: struct msg_command_data data;
134: struct cmd_ctx ctx;
135: struct cmd_list *cmdlist;
136: struct cmd *cmd;
137:
138: if (hdr->size < sizeof data)
139: fatalx("bad MSG_COMMAND size");
140: buffer_read(c->in, &data, sizeof data);
141:
142: cmdlist = cmd_list_recv(c->in);
143: server_activity = time(NULL);
144:
145: ctx.error = server_msg_fn_command_error;
146: ctx.print = server_msg_fn_command_print;
147: ctx.info = server_msg_fn_command_info;
148:
149: ctx.msgdata = &data;
150: ctx.curclient = NULL;
151: ctx.cursession = NULL;
152:
153: ctx.cmdclient = c;
154:
155: if (data.pid != -1) {
156: TAILQ_FOREACH(cmd, cmdlist, qentry) {
157: if (cmd->entry->flags & CMD_CANTNEST) {
158: server_msg_fn_command_error(&ctx,
159: "sessions should be nested with care. "
160: "unset $TMUX to force");
161: cmd_list_free(cmdlist);
162: server_write_client(c, MSG_EXIT, NULL, 0);
163: return (0);
164: }
165: }
166: }
167:
168: if (cmd_list_exec(cmdlist, &ctx) != 1)
169: server_write_client(c, MSG_EXIT, NULL, 0);
170: cmd_list_free(cmdlist);
171: return (0);
172: }
173:
174: int
175: server_msg_fn_identify(struct hdr *hdr, struct client *c)
176: {
177: struct msg_identify_data data;
178: char *term;
179:
180: if (hdr->size < sizeof data)
181: fatalx("bad MSG_IDENTIFY size");
182: buffer_read(c->in, &data, sizeof data);
183: term = cmd_recv_string(c->in);
184:
185: log_debug("identify msg from client: %u,%u (%d)",
186: data.sx, data.sy, data.version);
187:
188: if (data.version != PROTOCOL_VERSION) {
189: #define MSG "protocol version mismatch"
190: server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1);
191: #undef MSG
192: return (0);
193: }
194:
195: c->tty.sx = data.sx;
196: c->tty.sy = data.sy;
197:
198: c->cwd = NULL;
1.3 ! nicm 199: data.cwd[(sizeof data.cwd) - 1] = '\0';
1.1 nicm 200: if (*data.cwd != '\0')
201: c->cwd = xstrdup(data.cwd);
202:
203: data.tty[(sizeof data.tty) - 1] = '\0';
204: tty_init(&c->tty, data.tty, term);
205: if (data.flags & IDENTIFY_UTF8)
206: c->tty.flags |= TTY_UTF8;
207: if (data.flags & IDENTIFY_256COLOURS)
208: c->tty.term_flags |= TERM_256COLOURS;
209: else if (data.flags & IDENTIFY_88COLOURS)
210: c->tty.term_flags |= TERM_88COLOURS;
211: if (data.flags & IDENTIFY_HASDEFAULTS)
212: c->tty.term_flags |= TERM_HASDEFAULTS;
213: xfree(term);
214:
215: c->flags |= CLIENT_TERMINAL;
216:
217: return (0);
218: }
219:
220: int
221: server_msg_fn_resize(struct hdr *hdr, struct client *c)
222: {
223: struct msg_resize_data data;
224:
225: if (hdr->size != sizeof data)
226: fatalx("bad MSG_RESIZE size");
227: buffer_read(c->in, &data, sizeof data);
228:
229: log_debug("resize msg from client: %u,%u", data.sx, data.sy);
230:
231: c->tty.sx = data.sx;
232: if (c->tty.sx == 0)
233: c->tty.sx = 80;
234: c->tty.sy = data.sy;
235: if (c->tty.sy == 0)
236: c->tty.sy = 25;
237:
238: c->tty.cx = UINT_MAX;
239: c->tty.cy = UINT_MAX;
240: c->tty.rupper = UINT_MAX;
241: c->tty.rlower = UINT_MAX;
242:
243: recalculate_sizes();
244:
245: /* Always redraw this client. */
246: server_redraw_client(c);
247:
248: return (0);
249: }
250:
251: int
252: server_msg_fn_exiting(struct hdr *hdr, struct client *c)
253: {
254: if (hdr->size != 0)
255: fatalx("bad MSG_EXITING size");
256:
257: log_debug("exiting msg from client");
258:
259: c->session = NULL;
260:
261: tty_close(&c->tty, c->flags & CLIENT_SUSPENDED);
262:
263: server_write_client(c, MSG_EXITED, NULL, 0);
264:
265: return (0);
266: }
267:
268: int
269: server_msg_fn_unlock(struct hdr *hdr, struct client *c)
270: {
271: char *pass;
272:
273: if (hdr->size == 0)
274: fatalx("bad MSG_UNLOCK size");
275: pass = cmd_recv_string(c->in);
276:
277: log_debug("unlock msg from client");
278:
279: if (server_unlock(pass) != 0) {
280: #define MSG "bad password"
281: server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1);
282: #undef MSG
283: }
284:
285: server_write_client(c, MSG_EXIT, NULL, 0);
1.2 nicm 286:
287: memset(pass, 0, strlen(pass));
288: xfree(pass);
1.1 nicm 289:
290: return (0);
291: }
292:
293: int
294: server_msg_fn_wakeup(struct hdr *hdr, struct client *c)
295: {
296: if (hdr->size != 0)
297: fatalx("bad MSG_WAKEUP size");
298:
299: log_debug("wakeup msg from client");
300:
301: c->flags &= ~CLIENT_SUSPENDED;
302: tty_start_tty(&c->tty);
303: server_redraw_client(c);
304:
305: return (0);
306: }