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

Annotation of src/usr.bin/tmux/cmd.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: #include <sys/time.h>
        !            21:
        !            22: #include <stdlib.h>
        !            23: #include <string.h>
        !            24: #include <unistd.h>
        !            25:
        !            26: #include "tmux.h"
        !            27:
        !            28: const struct cmd_entry *cmd_table[] = {
        !            29:        &cmd_attach_session_entry,
        !            30:        &cmd_bind_key_entry,
        !            31:        &cmd_break_pane_entry,
        !            32:        &cmd_choose_session_entry,
        !            33:        &cmd_choose_window_entry,
        !            34:        &cmd_clear_history_entry,
        !            35:        &cmd_clock_mode_entry,
        !            36:        &cmd_command_prompt_entry,
        !            37:        &cmd_confirm_before_entry,
        !            38:        &cmd_copy_buffer_entry,
        !            39:        &cmd_copy_mode_entry,
        !            40:        &cmd_delete_buffer_entry,
        !            41:        &cmd_detach_client_entry,
        !            42:        &cmd_down_pane_entry,
        !            43:        &cmd_find_window_entry,
        !            44:        &cmd_has_session_entry,
        !            45:        &cmd_kill_pane_entry,
        !            46:        &cmd_kill_server_entry,
        !            47:        &cmd_kill_session_entry,
        !            48:        &cmd_kill_window_entry,
        !            49:        &cmd_last_window_entry,
        !            50:        &cmd_link_window_entry,
        !            51:        &cmd_list_buffers_entry,
        !            52:        &cmd_list_clients_entry,
        !            53:        &cmd_list_commands_entry,
        !            54:        &cmd_list_keys_entry,
        !            55:        &cmd_list_sessions_entry,
        !            56:        &cmd_list_windows_entry,
        !            57:        &cmd_load_buffer_entry,
        !            58:        &cmd_lock_server_entry,
        !            59:        &cmd_move_window_entry,
        !            60:        &cmd_new_session_entry,
        !            61:        &cmd_new_window_entry,
        !            62:        &cmd_next_layout_entry,
        !            63:        &cmd_next_window_entry,
        !            64:        &cmd_paste_buffer_entry,
        !            65:        &cmd_previous_layout_entry,
        !            66:        &cmd_previous_window_entry,
        !            67:        &cmd_refresh_client_entry,
        !            68:        &cmd_rename_session_entry,
        !            69:        &cmd_rename_window_entry,
        !            70:        &cmd_resize_pane_entry,
        !            71:        &cmd_respawn_window_entry,
        !            72:        &cmd_rotate_window_entry,
        !            73:        &cmd_save_buffer_entry,
        !            74:        &cmd_scroll_mode_entry,
        !            75:        &cmd_select_layout_entry,
        !            76:        &cmd_select_pane_entry,
        !            77:        &cmd_select_prompt_entry,
        !            78:        &cmd_select_window_entry,
        !            79:        &cmd_send_keys_entry,
        !            80:        &cmd_send_prefix_entry,
        !            81:        &cmd_server_info_entry,
        !            82:        &cmd_set_buffer_entry,
        !            83:        &cmd_set_option_entry,
        !            84:        &cmd_set_password_entry,
        !            85:        &cmd_set_window_option_entry,
        !            86:        &cmd_show_buffer_entry,
        !            87:        &cmd_show_options_entry,
        !            88:        &cmd_show_window_options_entry,
        !            89:        &cmd_source_file_entry,
        !            90:        &cmd_split_window_entry,
        !            91:        &cmd_start_server_entry,
        !            92:        &cmd_suspend_client_entry,
        !            93:        &cmd_swap_pane_entry,
        !            94:        &cmd_swap_window_entry,
        !            95:        &cmd_switch_client_entry,
        !            96:        &cmd_unbind_key_entry,
        !            97:        &cmd_unlink_window_entry,
        !            98:        &cmd_up_pane_entry,
        !            99:        NULL
        !           100: };
        !           101:
        !           102: struct cmd *
        !           103: cmd_parse(int argc, char **argv, char **cause)
        !           104: {
        !           105:        const struct cmd_entry **entryp, *entry;
        !           106:        struct cmd              *cmd;
        !           107:        char                     s[BUFSIZ];
        !           108:        int                      opt;
        !           109:
        !           110:        *cause = NULL;
        !           111:        if (argc == 0)
        !           112:                return (NULL);
        !           113:
        !           114:        entry = NULL;
        !           115:        for (entryp = cmd_table; *entryp != NULL; entryp++) {
        !           116:                if ((*entryp)->alias != NULL &&
        !           117:                    strcmp((*entryp)->alias, argv[0]) == 0) {
        !           118:                        entry = *entryp;
        !           119:                        break;
        !           120:                }
        !           121:
        !           122:                if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
        !           123:                        continue;
        !           124:                if (entry != NULL)
        !           125:                        goto ambiguous;
        !           126:                entry = *entryp;
        !           127:
        !           128:                /* Bail now if an exact match. */
        !           129:                if (strcmp(entry->name, argv[0]) == 0)
        !           130:                        break;
        !           131:        }
        !           132:        if (entry == NULL) {
        !           133:                xasprintf(cause, "unknown command: %s", argv[0]);
        !           134:                return (NULL);
        !           135:        }
        !           136:
        !           137:        optreset = 1;
        !           138:        optind = 1;
        !           139:        if (entry->parse == NULL) {
        !           140:                while ((opt = getopt(argc, argv, "")) != -1) {
        !           141:                        switch (opt) {
        !           142:                        default:
        !           143:                                goto usage;
        !           144:                        }
        !           145:                }
        !           146:                argc -= optind;
        !           147:                argv += optind;
        !           148:                if (argc != 0)
        !           149:                        goto usage;
        !           150:        }
        !           151:
        !           152:        cmd = xmalloc(sizeof *cmd);
        !           153:        cmd->entry = entry;
        !           154:        cmd->data = NULL;
        !           155:        if (entry->parse != NULL) {
        !           156:                if (entry->parse(cmd, argc, argv, cause) != 0) {
        !           157:                        xfree(cmd);
        !           158:                        return (NULL);
        !           159:                }
        !           160:        }
        !           161:        return (cmd);
        !           162:
        !           163: ambiguous:
        !           164:        *s = '\0';
        !           165:        for (entryp = cmd_table; *entryp != NULL; entryp++) {
        !           166:                if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
        !           167:                        continue;
        !           168:                if (strlcat(s, (*entryp)->name, sizeof s) >= sizeof s)
        !           169:                        break;
        !           170:                if (strlcat(s, ", ", sizeof s) >= sizeof s)
        !           171:                        break;
        !           172:        }
        !           173:        s[strlen(s) - 2] = '\0';
        !           174:        xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s);
        !           175:        return (NULL);
        !           176:
        !           177: usage:
        !           178:        xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
        !           179:        return (NULL);
        !           180: }
        !           181:
        !           182: int
        !           183: cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
        !           184: {
        !           185:        if (server_locked) {
        !           186:                ctx->error(ctx, "server is locked");
        !           187:                return (-1);
        !           188:        }
        !           189:        return (cmd->entry->exec(cmd, ctx));
        !           190: }
        !           191:
        !           192: void
        !           193: cmd_send(struct cmd *cmd, struct buffer *b)
        !           194: {
        !           195:        const struct cmd_entry **entryp;
        !           196:        u_int                    n;
        !           197:
        !           198:        n = 0;
        !           199:        for (entryp = cmd_table; *entryp != NULL; entryp++) {
        !           200:                if (*entryp == cmd->entry)
        !           201:                        break;
        !           202:                n++;
        !           203:        }
        !           204:        if (*entryp == NULL)
        !           205:                fatalx("command not found");
        !           206:
        !           207:        buffer_write(b, &n, sizeof n);
        !           208:
        !           209:        if (cmd->entry->send != NULL)
        !           210:                cmd->entry->send(cmd, b);
        !           211: }
        !           212:
        !           213: struct cmd *
        !           214: cmd_recv(struct buffer *b)
        !           215: {
        !           216:        const struct cmd_entry **entryp;
        !           217:        struct cmd              *cmd;
        !           218:        u_int                    m, n;
        !           219:
        !           220:        buffer_read(b, &m, sizeof m);
        !           221:
        !           222:        n = 0;
        !           223:        for (entryp = cmd_table; *entryp != NULL; entryp++) {
        !           224:                if (n == m)
        !           225:                        break;
        !           226:                n++;
        !           227:        }
        !           228:        if (*entryp == NULL)
        !           229:                fatalx("command not found");
        !           230:
        !           231:        cmd = xmalloc(sizeof *cmd);
        !           232:        cmd->entry = *entryp;
        !           233:
        !           234:        if (cmd->entry->recv != NULL)
        !           235:                cmd->entry->recv(cmd, b);
        !           236:        return (cmd);
        !           237: }
        !           238:
        !           239: void
        !           240: cmd_free(struct cmd *cmd)
        !           241: {
        !           242:        if (cmd->data != NULL && cmd->entry->free != NULL)
        !           243:                cmd->entry->free(cmd);
        !           244:        xfree(cmd);
        !           245: }
        !           246:
        !           247: size_t
        !           248: cmd_print(struct cmd *cmd, char *buf, size_t len)
        !           249: {
        !           250:        if (cmd->entry->print == NULL) {
        !           251:                return (xsnprintf(buf, len, "%s", cmd->entry->name));
        !           252:        }
        !           253:        return (cmd->entry->print(cmd, buf, len));
        !           254: }
        !           255:
        !           256: void
        !           257: cmd_send_string(struct buffer *b, const char *s)
        !           258: {
        !           259:        size_t  n;
        !           260:
        !           261:        if (s == NULL) {
        !           262:                n = 0;
        !           263:                buffer_write(b, &n, sizeof n);
        !           264:                return;
        !           265:        }
        !           266:
        !           267:        n = strlen(s) + 1;
        !           268:        buffer_write(b, &n, sizeof n);
        !           269:
        !           270:        buffer_write(b, s, n);
        !           271: }
        !           272:
        !           273: char *
        !           274: cmd_recv_string(struct buffer *b)
        !           275: {
        !           276:        char   *s;
        !           277:        size_t  n;
        !           278:
        !           279:        buffer_read(b, &n, sizeof n);
        !           280:
        !           281:        if (n == 0)
        !           282:                return (NULL);
        !           283:
        !           284:        s = xmalloc(n);
        !           285:        buffer_read(b, s, n);
        !           286:        s[n - 1] = '\0';
        !           287:
        !           288:        return (s);
        !           289: }
        !           290:
        !           291: struct session *
        !           292: cmd_current_session(struct cmd_ctx *ctx)
        !           293: {
        !           294:        struct msg_command_data *data = ctx->msgdata;
        !           295:        struct timeval          *tv;
        !           296:        struct session          *s, *newest = NULL;
        !           297:        u_int                    i;
        !           298:
        !           299:        if (ctx->cursession != NULL)
        !           300:                return (ctx->cursession);
        !           301:
        !           302:        if (data != NULL && data->pid != -1) {
        !           303:                if (data->pid != getpid()) {
        !           304:                        ctx->error(ctx, "wrong server: %ld", (long) data->pid);
        !           305:                        return (NULL);
        !           306:                }
        !           307:                if (data->idx > ARRAY_LENGTH(&sessions)) {
        !           308:                        ctx->error(ctx, "index out of range: %d", data->idx);
        !           309:                        return (NULL);
        !           310:                }
        !           311:                if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
        !           312:                        ctx->error(ctx, "session doesn't exist: %u", data->idx);
        !           313:                        return (NULL);
        !           314:                }
        !           315:                return (s);
        !           316:        }
        !           317:
        !           318:        tv = NULL;
        !           319:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
        !           320:                s = ARRAY_ITEM(&sessions, i);
        !           321:                if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) {
        !           322:                        newest = ARRAY_ITEM(&sessions, i);
        !           323:                        tv = &s->tv;
        !           324:                }
        !           325:        }
        !           326:        return (newest);
        !           327: }
        !           328:
        !           329: struct client *
        !           330: cmd_find_client(struct cmd_ctx *ctx, const char *arg)
        !           331: {
        !           332:        struct client   *c;
        !           333:
        !           334:        if (arg == NULL)
        !           335:                c = ctx->curclient;
        !           336:        else {
        !           337:                if ((c = arg_parse_client(arg)) == NULL) {
        !           338:                        if (arg != NULL)
        !           339:                                ctx->error(ctx, "client not found: %s", arg);
        !           340:                        else
        !           341:                                ctx->error(ctx, "no client found");
        !           342:                }
        !           343:        }
        !           344:        return (c);
        !           345: }
        !           346:
        !           347: struct session *
        !           348: cmd_find_session(struct cmd_ctx *ctx, const char *arg)
        !           349: {
        !           350:        struct session  *s;
        !           351:
        !           352:        if (arg == NULL)
        !           353:                s = cmd_current_session(ctx);
        !           354:        else {
        !           355:                if ((s = arg_parse_session(arg)) == NULL) {
        !           356:                        if (arg != NULL)
        !           357:                                ctx->error(ctx, "session not found: %s", arg);
        !           358:                        else
        !           359:                                ctx->error(ctx, "no session found");
        !           360:                }
        !           361:        }
        !           362:        return (s);
        !           363: }
        !           364:
        !           365: struct winlink *
        !           366: cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
        !           367: {
        !           368:        struct session  *s;
        !           369:        struct winlink  *wl;
        !           370:        int              idx;
        !           371:
        !           372:        wl = NULL;
        !           373:        if (arg_parse_window(arg, &s, &idx) != 0) {
        !           374:                ctx->error(ctx, "bad window: %s", arg);
        !           375:                return (NULL);
        !           376:        }
        !           377:        if (s == NULL)
        !           378:                s = ctx->cursession;
        !           379:        if (s == NULL)
        !           380:                s = cmd_current_session(ctx);
        !           381:        if (s == NULL)
        !           382:                return (NULL);
        !           383:        if (sp != NULL)
        !           384:                *sp = s;
        !           385:
        !           386:        if (idx == -1)
        !           387:                wl = s->curw;
        !           388:        else
        !           389:                wl = winlink_find_by_index(&s->windows, idx);
        !           390:        if (wl == NULL)
        !           391:                ctx->error(ctx, "window not found: %s:%d", s->name, idx);
        !           392:        return (wl);
        !           393: }