[BACK]Return to server-msg.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/server-msg.c, Revision 1.1

1.1     ! nicm        1: /* $OpenBSD$ */
        !             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;
        !           199:        if (*data.cwd != '\0')
        !           200:                c->cwd = xstrdup(data.cwd);
        !           201:
        !           202:        data.tty[(sizeof data.tty) - 1] = '\0';
        !           203:        tty_init(&c->tty, data.tty, term);
        !           204:        if (data.flags & IDENTIFY_UTF8)
        !           205:                c->tty.flags |= TTY_UTF8;
        !           206:        if (data.flags & IDENTIFY_256COLOURS)
        !           207:                c->tty.term_flags |= TERM_256COLOURS;
        !           208:        else if (data.flags & IDENTIFY_88COLOURS)
        !           209:                c->tty.term_flags |= TERM_88COLOURS;
        !           210:        if (data.flags & IDENTIFY_HASDEFAULTS)
        !           211:                c->tty.term_flags |= TERM_HASDEFAULTS;
        !           212:        xfree(term);
        !           213:
        !           214:        c->flags |= CLIENT_TERMINAL;
        !           215:
        !           216:        return (0);
        !           217: }
        !           218:
        !           219: int
        !           220: server_msg_fn_resize(struct hdr *hdr, struct client *c)
        !           221: {
        !           222:        struct msg_resize_data  data;
        !           223:
        !           224:        if (hdr->size != sizeof data)
        !           225:                fatalx("bad MSG_RESIZE size");
        !           226:        buffer_read(c->in, &data, sizeof data);
        !           227:
        !           228:        log_debug("resize msg from client: %u,%u", data.sx, data.sy);
        !           229:
        !           230:        c->tty.sx = data.sx;
        !           231:        if (c->tty.sx == 0)
        !           232:                c->tty.sx = 80;
        !           233:        c->tty.sy = data.sy;
        !           234:        if (c->tty.sy == 0)
        !           235:                c->tty.sy = 25;
        !           236:
        !           237:        c->tty.cx = UINT_MAX;
        !           238:        c->tty.cy = UINT_MAX;
        !           239:        c->tty.rupper = UINT_MAX;
        !           240:        c->tty.rlower = UINT_MAX;
        !           241:
        !           242:        recalculate_sizes();
        !           243:
        !           244:        /* Always redraw this client. */
        !           245:        server_redraw_client(c);
        !           246:
        !           247:        return (0);
        !           248: }
        !           249:
        !           250: int
        !           251: server_msg_fn_exiting(struct hdr *hdr, struct client *c)
        !           252: {
        !           253:        if (hdr->size != 0)
        !           254:                fatalx("bad MSG_EXITING size");
        !           255:
        !           256:        log_debug("exiting msg from client");
        !           257:
        !           258:        c->session = NULL;
        !           259:
        !           260:        tty_close(&c->tty, c->flags & CLIENT_SUSPENDED);
        !           261:
        !           262:        server_write_client(c, MSG_EXITED, NULL, 0);
        !           263:
        !           264:        return (0);
        !           265: }
        !           266:
        !           267: int
        !           268: server_msg_fn_unlock(struct hdr *hdr, struct client *c)
        !           269: {
        !           270:         char   *pass;
        !           271:
        !           272:        if (hdr->size == 0)
        !           273:                fatalx("bad MSG_UNLOCK size");
        !           274:        pass = cmd_recv_string(c->in);
        !           275:
        !           276:        log_debug("unlock msg from client");
        !           277:
        !           278:        if (server_unlock(pass) != 0) {
        !           279: #define MSG "bad password"
        !           280:                server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1);
        !           281:                server_write_client(c, MSG_EXIT, NULL, 0);
        !           282:                return (0);
        !           283: #undef MSG
        !           284:        }
        !           285:
        !           286:        server_write_client(c, MSG_EXIT, NULL, 0);
        !           287:
        !           288:        return (0);
        !           289: }
        !           290:
        !           291: int
        !           292: server_msg_fn_wakeup(struct hdr *hdr, struct client *c)
        !           293: {
        !           294:        if (hdr->size != 0)
        !           295:                fatalx("bad MSG_WAKEUP size");
        !           296:
        !           297:        log_debug("wakeup msg from client");
        !           298:
        !           299:        c->flags &= ~CLIENT_SUSPENDED;
        !           300:        tty_start_tty(&c->tty);
        !           301:        server_redraw_client(c);
        !           302:
        !           303:        return (0);
        !           304: }