Annotation of src/usr.bin/tmux/server-msg.c, Revision 1.9
1.9 ! nicm 1: /* $OpenBSD: server-msg.c,v 1.8 2009/07/29 14:17:26 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.9 ! nicm 29: void server_msg_command(struct client *, struct msg_command_data *);
! 30: void server_msg_identify(struct client *, struct msg_identify_data *);
! 31: void server_msg_resize(struct client *, struct msg_resize_data *);
! 32:
! 33: void printflike2 server_msg_command_error(struct cmd_ctx *, const char *, ...);
! 34: void printflike2 server_msg_command_print(struct cmd_ctx *, const char *, ...);
! 35: void printflike2 server_msg_command_info(struct cmd_ctx *, const char *, ...);
1.1 nicm 36:
37: int
38: server_msg_dispatch(struct client *c)
39: {
40: struct hdr hdr;
1.9 ! nicm 41: struct msg_command_data commanddata;
! 42: struct msg_identify_data identifydata;
! 43: struct msg_resize_data resizedata;
! 44: struct msg_unlock_data unlockdata;
1.1 nicm 45:
46: for (;;) {
47: if (BUFFER_USED(c->in) < sizeof hdr)
48: return (0);
49: memcpy(&hdr, BUFFER_OUT(c->in), sizeof hdr);
50: if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size)
51: return (0);
52: buffer_remove(c->in, sizeof hdr);
53:
1.9 ! nicm 54: switch (hdr.type) {
! 55: case MSG_COMMAND:
! 56: if (hdr.size != sizeof commanddata)
! 57: fatalx("bad MSG_COMMAND size");
! 58: buffer_read(c->in, &commanddata, sizeof commanddata);
! 59:
! 60: server_msg_command(c, &commanddata);
! 61: break;
! 62: case MSG_IDENTIFY:
! 63: if (hdr.size != sizeof identifydata)
! 64: fatalx("bad MSG_IDENTIFY size");
! 65: buffer_read(c->in, &identifydata, sizeof identifydata);
! 66:
! 67: server_msg_identify(c, &identifydata);
! 68: break;
! 69: case MSG_RESIZE:
! 70: if (hdr.size != sizeof resizedata)
! 71: fatalx("bad MSG_RESIZE size");
! 72: buffer_read(c->in, &resizedata, sizeof resizedata);
! 73:
! 74: server_msg_resize(c, &resizedata);
! 75: break;
! 76: case MSG_EXITING:
! 77: if (hdr.size != 0)
! 78: fatalx("bad MSG_EXITING size");
! 79:
! 80: c->session = NULL;
! 81: tty_close(&c->tty, c->flags & CLIENT_SUSPENDED);
! 82: server_write_client(c, MSG_EXITED, NULL, 0);
! 83: break;
! 84: case MSG_UNLOCK:
! 85: if (hdr.size != sizeof unlockdata)
! 86: fatalx("bad MSG_UNLOCK size");
! 87: buffer_read(c->in, &unlockdata, sizeof unlockdata);
! 88:
! 89: unlockdata.pass[(sizeof unlockdata.pass) - 1] = '\0';
! 90: if (server_unlock(unlockdata.pass) != 0)
! 91: server_write_error(c, "bad password");
! 92: memset(&unlockdata, 0, sizeof unlockdata);
! 93: server_write_client(c, MSG_EXIT, NULL, 0);
! 94: break;
! 95: case MSG_WAKEUP:
! 96: if (hdr.size != 0)
! 97: fatalx("bad MSG_WAKEUP size");
! 98:
! 99: c->flags &= ~CLIENT_SUSPENDED;
! 100: tty_start_tty(&c->tty);
! 101: server_redraw_client(c);
! 102: break;
! 103: default:
! 104: fatalx("unexpected message");
1.1 nicm 105: }
106: }
107: }
108:
109: void printflike2
1.9 ! nicm 110: server_msg_command_error(struct cmd_ctx *ctx, const char *fmt, ...)
1.1 nicm 111: {
1.7 nicm 112: struct msg_print_data data;
113: va_list ap;
1.1 nicm 114:
115: va_start(ap, fmt);
1.7 nicm 116: xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
1.1 nicm 117: va_end(ap);
118:
1.7 nicm 119: server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
1.1 nicm 120: }
121:
122: void printflike2
1.9 ! nicm 123: server_msg_command_print(struct cmd_ctx *ctx, const char *fmt, ...)
1.1 nicm 124: {
1.7 nicm 125: struct msg_print_data data;
126: va_list ap;
1.1 nicm 127:
128: va_start(ap, fmt);
1.7 nicm 129: xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
1.1 nicm 130: va_end(ap);
131:
1.7 nicm 132: server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
1.1 nicm 133: }
134:
135: void printflike2
1.9 ! nicm 136: server_msg_command_info(struct cmd_ctx *ctx, const char *fmt, ...)
1.1 nicm 137: {
1.7 nicm 138: struct msg_print_data data;
139: va_list ap;
1.1 nicm 140:
141: if (be_quiet)
142: return;
143:
144: va_start(ap, fmt);
1.7 nicm 145: xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
1.1 nicm 146: va_end(ap);
147:
1.7 nicm 148: server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
1.1 nicm 149: }
150:
1.6 nicm 151: void
1.9 ! nicm 152: server_msg_command(struct client *c, struct msg_command_data *data)
1.1 nicm 153: {
1.9 ! nicm 154: struct cmd_ctx ctx;
! 155: struct cmd_list *cmdlist = NULL;
! 156: struct cmd *cmd;
! 157: int argc;
! 158: char **argv, *cause;
1.1 nicm 159:
160: server_activity = time(NULL);
161:
1.9 ! nicm 162: ctx.error = server_msg_command_error;
! 163: ctx.print = server_msg_command_print;
! 164: ctx.info = server_msg_command_info;
1.1 nicm 165:
1.9 ! nicm 166: ctx.msgdata = data;
1.1 nicm 167: ctx.curclient = NULL;
168: ctx.cursession = NULL;
169:
170: ctx.cmdclient = c;
171:
1.9 ! nicm 172: argc = data->argc;
! 173: data->argv[(sizeof data->argv) - 1] = '\0';
! 174: if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
! 175: server_msg_command_error(&ctx, "command too long");
1.7 nicm 176: goto error;
177: }
178:
179: if (argc == 0) {
180: argc = 1;
181: argv = xcalloc(1, sizeof *argv);
182: *argv = xstrdup("new-session");
183: }
184:
185: if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
1.9 ! nicm 186: server_msg_command_error(&ctx, "%s", cause);
1.7 nicm 187: cmd_free_argv(argc, argv);
188: goto error;
189: }
190: cmd_free_argv(argc, argv);
191:
1.9 ! nicm 192: if (data->pid != -1) {
1.1 nicm 193: TAILQ_FOREACH(cmd, cmdlist, qentry) {
194: if (cmd->entry->flags & CMD_CANTNEST) {
1.9 ! nicm 195: server_msg_command_error(&ctx,
1.1 nicm 196: "sessions should be nested with care. "
197: "unset $TMUX to force");
1.7 nicm 198: goto error;
1.1 nicm 199: }
200: }
201: }
202:
203: if (cmd_list_exec(cmdlist, &ctx) != 1)
204: server_write_client(c, MSG_EXIT, NULL, 0);
205: cmd_list_free(cmdlist);
1.7 nicm 206: return;
207:
208: error:
209: if (cmdlist != NULL)
210: cmd_list_free(cmdlist);
211: server_write_client(c, MSG_EXIT, NULL, 0);
1.1 nicm 212: }
213:
1.6 nicm 214: void
1.9 ! nicm 215: server_msg_identify(struct client *c, struct msg_identify_data *data)
1.1 nicm 216: {
1.9 ! nicm 217: if (data->version != PROTOCOL_VERSION) {
1.7 nicm 218: server_write_error(c, "protocol version mismatch");
1.6 nicm 219: return;
1.1 nicm 220: }
221:
1.9 ! nicm 222: c->tty.sx = data->sx;
! 223: c->tty.sy = data->sy;
1.1 nicm 224:
225: c->cwd = NULL;
1.9 ! nicm 226: data->cwd[(sizeof data->cwd) - 1] = '\0';
! 227: if (*data->cwd != '\0')
! 228: c->cwd = xstrdup(data->cwd);
! 229:
! 230: data->tty[(sizeof data->tty) - 1] = '\0';
! 231: data->term[(sizeof data->term) - 1] = '\0';
! 232: tty_init(&c->tty, data->tty, data->term);
! 233: if (data->flags & IDENTIFY_UTF8)
1.1 nicm 234: c->tty.flags |= TTY_UTF8;
1.9 ! nicm 235: if (data->flags & IDENTIFY_256COLOURS)
1.1 nicm 236: c->tty.term_flags |= TERM_256COLOURS;
1.9 ! nicm 237: else if (data->flags & IDENTIFY_88COLOURS)
1.1 nicm 238: c->tty.term_flags |= TERM_88COLOURS;
1.9 ! nicm 239: if (data->flags & IDENTIFY_HASDEFAULTS)
1.1 nicm 240: c->tty.term_flags |= TERM_HASDEFAULTS;
1.5 nicm 241:
1.1 nicm 242: c->flags |= CLIENT_TERMINAL;
243: }
244:
1.6 nicm 245: void
1.9 ! nicm 246: server_msg_resize(struct client *c, struct msg_resize_data *data)
1.1 nicm 247: {
1.9 ! nicm 248: c->tty.sx = data->sx;
1.1 nicm 249: if (c->tty.sx == 0)
250: c->tty.sx = 80;
1.9 ! nicm 251: c->tty.sy = data->sy;
1.1 nicm 252: if (c->tty.sy == 0)
253: c->tty.sy = 25;
254:
255: c->tty.cx = UINT_MAX;
256: c->tty.cy = UINT_MAX;
257: c->tty.rupper = UINT_MAX;
258: c->tty.rlower = UINT_MAX;
259:
260: recalculate_sizes();
261:
262: /* Always redraw this client. */
263: server_redraw_client(c);
264: }