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