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