[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.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: }