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

Annotation of src/usr.bin/tmux/cmd-generic.c, Revision 1.8

1.8     ! nicm        1: /* $OpenBSD: cmd-generic.c,v 1.7 2009/08/26 18:09:52 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2008 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 <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include "tmux.h"
                     25:
1.8     ! nicm       26: int    cmd_getopt(int, char **, const char *, const char *);
        !            27: int    cmd_parse_flags(int, const char *, uint64_t *);
1.3       nicm       28: size_t cmd_print_flags(char *, size_t, size_t, uint64_t);
1.6       nicm       29: int    cmd_fill_argument(int, char **, char **, int, char **);
1.1       nicm       30:
                     31: size_t
                     32: cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
                     33: {
                     34:        if (strchr(arg, ' ') != NULL)
                     35:                return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg));
                     36:        return (xsnprintf(buf, len, "%s%s", prefix, arg));
                     37: }
                     38:
1.8     ! nicm       39: /* Append two flag strings together and call getopt. */
1.1       nicm       40: int
1.8     ! nicm       41: cmd_getopt(int argc, char **argv, const char *flagstr, const char *chflagstr)
1.1       nicm       42: {
1.8     ! nicm       43:        char    tmp[BUFSIZ];
1.3       nicm       44:
1.8     ! nicm       45:        if (strlcpy(tmp, flagstr, sizeof tmp) >= sizeof tmp)
        !            46:                fatalx("strlcpy overflow");
        !            47:        if (strlcat(tmp, chflagstr, sizeof tmp) >= sizeof tmp)
        !            48:                fatalx("strlcat overflow");
        !            49:        return (getopt(argc, argv, tmp));
        !            50: }
1.3       nicm       51:
1.8     ! nicm       52: /* Return if flag character is set. */
        !            53: int
        !            54: cmd_check_flag(uint64_t chflags, int flag)
        !            55: {
        !            56:        if (flag >= 'A' && flag <= 'Z')
        !            57:                flag = 26 + flag - 'A';
        !            58:        else if (flag >= 'a' && flag <= 'z')
        !            59:                flag = flag - 'a';
        !            60:        else
        !            61:                return (0);
        !            62:        return ((chflags & (1ULL << flag)) != 0);
        !            63: }
1.3       nicm       64:
1.8     ! nicm       65: /* Set flag character. */
        !            66: void
        !            67: cmd_set_flag(uint64_t *chflags, int flag)
        !            68: {
        !            69:        if (flag >= 'A' && flag <= 'Z')
        !            70:                flag = 26 + flag - 'A';
        !            71:        else if (flag >= 'a' && flag <= 'z')
        !            72:                flag = flag - 'a';
        !            73:        else
        !            74:                return;
        !            75:        (*chflags) |= (1ULL << flag);
1.3       nicm       76: }
                     77:
1.8     ! nicm       78: /* If this option is expected, set it in chflags, otherwise return -1. */
1.3       nicm       79: int
1.8     ! nicm       80: cmd_parse_flags(int opt, const char *chflagstr, uint64_t *chflags)
1.3       nicm       81: {
1.8     ! nicm       82:        if (strchr(chflagstr, opt) == NULL)
        !            83:                return (-1);
        !            84:        cmd_set_flag(chflags, opt);
        !            85:        return (0);
1.1       nicm       86: }
                     87:
1.3       nicm       88: /* Print the flags supported in chflags. */
1.1       nicm       89: size_t
1.3       nicm       90: cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
1.1       nicm       91: {
1.3       nicm       92:        u_char  ch;
1.1       nicm       93:        size_t  boff = off;
                     94:
1.3       nicm       95:        if (chflags == 0)
1.1       nicm       96:                return (0);
                     97:        off += xsnprintf(buf + off, len - off, " -");
1.3       nicm       98:
                     99:        for (ch = 0; ch < 26; ch++) {
1.8     ! nicm      100:                if (cmd_check_flag(chflags, 'a' + ch))
1.3       nicm      101:                        off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
1.8     ! nicm      102:                if (cmd_check_flag(chflags, 'A' + ch))
1.3       nicm      103:                        off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
                    104:        }
1.1       nicm      105:        return (off - boff);
                    106: }
                    107:
                    108: int
1.6       nicm      109: cmd_fill_argument(int flags, char **arg, char **arg2, int argc, char **argv)
1.1       nicm      110: {
                    111:        *arg = NULL;
1.6       nicm      112:        *arg2 = NULL;
1.1       nicm      113:
                    114:        if (flags & CMD_ARG1) {
                    115:                if (argc != 1)
                    116:                        return (-1);
                    117:                *arg = xstrdup(argv[0]);
                    118:                return (0);
                    119:        }
                    120:
                    121:        if (flags & CMD_ARG01) {
                    122:                if (argc != 0 && argc != 1)
                    123:                        return (-1);
                    124:                if (argc == 1)
                    125:                        *arg = xstrdup(argv[0]);
                    126:                return (0);
                    127:        }
                    128:
1.6       nicm      129:        if (flags & CMD_ARG2) {
                    130:                if (argc != 2)
                    131:                        return (-1);
                    132:                *arg = xstrdup(argv[0]);
                    133:                *arg2 = xstrdup(argv[1]);
                    134:                return (0);
                    135:        }
                    136:
                    137:        if (flags & CMD_ARG12) {
                    138:                if (argc != 1 && argc != 2)
                    139:                        return (-1);
                    140:                *arg = xstrdup(argv[0]);
                    141:                if (argc == 2)
                    142:                        *arg2 = xstrdup(argv[1]);
                    143:                return (0);
                    144:        }
                    145:
1.1       nicm      146:        if (argc != 0)
                    147:                return (-1);
                    148:        return (0);
                    149: }
                    150:
                    151: void
                    152: cmd_target_init(struct cmd *self, unused int key)
                    153: {
                    154:        struct cmd_target_data  *data;
                    155:
                    156:        self->data = data = xmalloc(sizeof *data);
1.3       nicm      157:        data->chflags = 0;
1.1       nicm      158:        data->target = NULL;
                    159:        data->arg = NULL;
1.7       nicm      160:        data->arg2 = NULL;
1.1       nicm      161: }
                    162:
                    163: int
                    164: cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
                    165: {
                    166:        struct cmd_target_data  *data;
1.3       nicm      167:        const struct cmd_entry  *entry = self->entry;
1.1       nicm      168:        int                      opt;
                    169:
                    170:        /* Don't use the entry version since it may be dependent on key. */
                    171:        cmd_target_init(self, 0);
                    172:        data = self->data;
                    173:
1.3       nicm      174:        while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
1.8     ! nicm      175:                if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
1.1       nicm      176:                        continue;
                    177:                switch (opt) {
                    178:                case 't':
                    179:                        if (data->target == NULL)
                    180:                                data->target = xstrdup(optarg);
                    181:                        break;
                    182:                default:
                    183:                        goto usage;
                    184:                }
                    185:        }
                    186:        argc -= optind;
                    187:        argv += optind;
                    188:
1.6       nicm      189:        if (cmd_fill_argument(
                    190:            self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
1.1       nicm      191:                goto usage;
                    192:        return (0);
                    193:
                    194: usage:
                    195:        xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
                    196:
                    197:        self->entry->free(self);
                    198:        return (-1);
                    199: }
                    200:
                    201: void
                    202: cmd_target_free(struct cmd *self)
                    203: {
                    204:        struct cmd_target_data  *data = self->data;
                    205:
                    206:        if (data->target != NULL)
                    207:                xfree(data->target);
                    208:        if (data->arg != NULL)
                    209:                xfree(data->arg);
1.7       nicm      210:        if (data->arg2 != NULL)
                    211:                xfree(data->arg2);
1.1       nicm      212:        xfree(data);
                    213: }
                    214:
                    215: size_t
                    216: cmd_target_print(struct cmd *self, char *buf, size_t len)
                    217: {
                    218:        struct cmd_target_data  *data = self->data;
                    219:        size_t                   off = 0;
                    220:
                    221:        off += xsnprintf(buf, len, "%s", self->entry->name);
                    222:        if (data == NULL)
                    223:                return (off);
1.3       nicm      224:        off += cmd_print_flags(buf, len, off, data->chflags);
1.1       nicm      225:        if (off < len && data->target != NULL)
                    226:                off += cmd_prarg(buf + off, len - off, " -t ", data->target);
                    227:        if (off < len && data->arg != NULL)
                    228:                off += cmd_prarg(buf + off, len - off, " ", data->arg);
1.6       nicm      229:        if (off < len && data->arg2 != NULL)
                    230:                off += cmd_prarg(buf + off, len - off, " ", data->arg2);
1.1       nicm      231:        return (off);
                    232: }
                    233:
                    234: void
                    235: cmd_srcdst_init(struct cmd *self, unused int key)
                    236: {
                    237:        struct cmd_srcdst_data  *data;
                    238:
                    239:        self->data = data = xmalloc(sizeof *data);
1.3       nicm      240:        data->chflags = 0;
1.1       nicm      241:        data->src = NULL;
                    242:        data->dst = NULL;
                    243:        data->arg = NULL;
1.7       nicm      244:        data->arg2 = NULL;
1.1       nicm      245: }
                    246:
                    247: int
                    248: cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
                    249: {
                    250:        struct cmd_srcdst_data  *data;
1.3       nicm      251:        const struct cmd_entry  *entry = self->entry;
1.1       nicm      252:        int                      opt;
                    253:
                    254:        cmd_srcdst_init(self, 0);
                    255:        data = self->data;
                    256:
1.3       nicm      257:        while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) {
1.8     ! nicm      258:                if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
1.1       nicm      259:                        continue;
                    260:                switch (opt) {
                    261:                case 's':
                    262:                        if (data->src == NULL)
                    263:                                data->src = xstrdup(optarg);
                    264:                        break;
                    265:                case 't':
                    266:                        if (data->dst == NULL)
                    267:                                data->dst = xstrdup(optarg);
                    268:                        break;
                    269:                default:
                    270:                        goto usage;
                    271:                }
                    272:        }
                    273:        argc -= optind;
                    274:        argv += optind;
                    275:
1.6       nicm      276:        if (cmd_fill_argument(
                    277:            self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
1.1       nicm      278:                goto usage;
                    279:        return (0);
                    280:
                    281: usage:
                    282:        xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
                    283:
                    284:        self->entry->free(self);
                    285:        return (-1);
                    286: }
                    287:
                    288: void
                    289: cmd_srcdst_free(struct cmd *self)
                    290: {
                    291:        struct cmd_srcdst_data  *data = self->data;
                    292:
                    293:        if (data->src != NULL)
                    294:                xfree(data->src);
                    295:        if (data->dst != NULL)
                    296:                xfree(data->dst);
                    297:        if (data->arg != NULL)
                    298:                xfree(data->arg);
1.7       nicm      299:        if (data->arg2 != NULL)
                    300:                xfree(data->arg2);
1.1       nicm      301:        xfree(data);
                    302: }
                    303:
                    304: size_t
                    305: cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
                    306: {
                    307:        struct cmd_srcdst_data  *data = self->data;
                    308:        size_t                   off = 0;
                    309:
                    310:        off += xsnprintf(buf, len, "%s", self->entry->name);
                    311:        if (data == NULL)
                    312:                return (off);
1.3       nicm      313:        off += cmd_print_flags(buf, len, off, data->chflags);
1.1       nicm      314:        if (off < len && data->src != NULL)
                    315:                off += xsnprintf(buf + off, len - off, " -s %s", data->src);
                    316:        if (off < len && data->dst != NULL)
                    317:                off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
                    318:        if (off < len && data->arg != NULL)
                    319:                off += cmd_prarg(buf + off, len - off, " ", data->arg);
1.6       nicm      320:        if (off < len && data->arg2 != NULL)
                    321:                off += cmd_prarg(buf + off, len - off, " ", data->arg2);
1.1       nicm      322:        return (off);
                    323: }
                    324:
                    325: void
                    326: cmd_buffer_init(struct cmd *self, unused int key)
                    327: {
                    328:        struct cmd_buffer_data  *data;
                    329:
                    330:        self->data = data = xmalloc(sizeof *data);
1.3       nicm      331:        data->chflags = 0;
1.1       nicm      332:        data->target = NULL;
                    333:        data->buffer = -1;
                    334:        data->arg = NULL;
1.7       nicm      335:        data->arg2 = NULL;
1.1       nicm      336: }
                    337:
                    338: int
                    339: cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
                    340: {
                    341:        struct cmd_buffer_data  *data;
1.3       nicm      342:        const struct cmd_entry  *entry = self->entry;
1.1       nicm      343:        int                      opt, n;
                    344:        const char              *errstr;
                    345:
                    346:        cmd_buffer_init(self, 0);
                    347:        data = self->data;
                    348:
1.3       nicm      349:        while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) {
1.8     ! nicm      350:                if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
1.1       nicm      351:                        continue;
                    352:                switch (opt) {
                    353:                case 'b':
                    354:                        if (data->buffer == -1) {
                    355:                                n = strtonum(optarg, 0, INT_MAX, &errstr);
                    356:                                if (errstr != NULL) {
                    357:                                        xasprintf(cause, "buffer %s", errstr);
                    358:                                        goto error;
                    359:                                }
                    360:                                data->buffer = n;
                    361:                        }
                    362:                        break;
                    363:                case 't':
                    364:                        if (data->target == NULL)
                    365:                                data->target = xstrdup(optarg);
                    366:                        break;
                    367:                default:
                    368:                        goto usage;
                    369:                }
                    370:        }
                    371:        argc -= optind;
                    372:        argv += optind;
                    373:
1.6       nicm      374:        if (cmd_fill_argument(
                    375:            self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
1.1       nicm      376:                goto usage;
                    377:        return (0);
                    378:
                    379: usage:
                    380:        xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
                    381:
                    382: error:
                    383:        self->entry->free(self);
                    384:        return (-1);
                    385: }
                    386:
                    387: void
                    388: cmd_buffer_free(struct cmd *self)
                    389: {
                    390:        struct cmd_buffer_data  *data = self->data;
                    391:
                    392:        if (data->target != NULL)
                    393:                xfree(data->target);
                    394:        if (data->arg != NULL)
                    395:                xfree(data->arg);
1.7       nicm      396:        if (data->arg2 != NULL)
                    397:                xfree(data->arg2);
1.1       nicm      398:        xfree(data);
                    399: }
                    400:
                    401: size_t
                    402: cmd_buffer_print(struct cmd *self, char *buf, size_t len)
                    403: {
                    404:        struct cmd_buffer_data  *data = self->data;
                    405:        size_t                   off = 0;
                    406:
                    407:        off += xsnprintf(buf, len, "%s", self->entry->name);
                    408:        if (data == NULL)
                    409:                return (off);
1.3       nicm      410:        off += cmd_print_flags(buf, len, off, data->chflags);
1.1       nicm      411:        if (off < len && data->buffer != -1)
                    412:                off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
                    413:        if (off < len && data->target != NULL)
                    414:                off += cmd_prarg(buf + off, len - off, " -t ", data->target);
                    415:        if (off < len && data->arg != NULL)
                    416:                off += cmd_prarg(buf + off, len - off, " ", data->arg);
1.6       nicm      417:        if (off < len && data->arg2 != NULL)
                    418:                off += cmd_prarg(buf + off, len - off, " ", data->arg2);
1.1       nicm      419:        return (off);
                    420: }