[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.4

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