Annotation of src/usr.bin/tmux/cmd-generic.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD$ */
! 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:
! 26: #define CMD_FLAGS "adDgkuU"
! 27: #define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_BIGDFLAG|CMD_GFLAG|CMD_KFLAG| \
! 28: CMD_UFLAG|CMD_BIGUFLAG)
! 29:
! 30: int cmd_do_flags(int, int, int *);
! 31: size_t cmd_print_flags(char *, size_t, size_t, int);
! 32: int cmd_fill_argument(int, char **, int, char **);
! 33:
! 34: size_t
! 35: cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
! 36: {
! 37: if (strchr(arg, ' ') != NULL)
! 38: return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg));
! 39: return (xsnprintf(buf, len, "%s%s", prefix, arg));
! 40: }
! 41:
! 42: int
! 43: cmd_do_flags(int opt, int iflags, int *oflags)
! 44: {
! 45: switch (opt) {
! 46: case 'a':
! 47: if (iflags & CMD_AFLAG) {
! 48: (*oflags) |= CMD_AFLAG;
! 49: return (0);
! 50: }
! 51: return (-1);
! 52: case 'd':
! 53: if (iflags & CMD_DFLAG) {
! 54: (*oflags) |= CMD_DFLAG;
! 55: return (0);
! 56: }
! 57: return (-1);
! 58: case 'D':
! 59: if (iflags & CMD_BIGDFLAG) {
! 60: (*oflags) |= CMD_BIGDFLAG;
! 61: return (0);
! 62: }
! 63: return (-1);
! 64: case 'g':
! 65: if (iflags & CMD_GFLAG) {
! 66: (*oflags) |= CMD_GFLAG;
! 67: return (0);
! 68: }
! 69: return (-1);
! 70: case 'k':
! 71: if (iflags & CMD_KFLAG) {
! 72: (*oflags) |= CMD_KFLAG;
! 73: return (0);
! 74: }
! 75: return (-1);
! 76: case 'u':
! 77: if (iflags & CMD_UFLAG) {
! 78: (*oflags) |= CMD_UFLAG;
! 79: return (0);
! 80: }
! 81: return (-1);
! 82: case 'U':
! 83: if (iflags & CMD_BIGUFLAG) {
! 84: (*oflags) |= CMD_BIGUFLAG;
! 85: return (0);
! 86: }
! 87: return (-1);
! 88: }
! 89: return (1);
! 90: }
! 91:
! 92: size_t
! 93: cmd_print_flags(char *buf, size_t len, size_t off, int flags)
! 94: {
! 95: size_t boff = off;
! 96:
! 97: if ((flags & CMD_FLAGMASK) == 0)
! 98: return (0);
! 99: off += xsnprintf(buf + off, len - off, " -");
! 100: if (off < len && flags & CMD_AFLAG)
! 101: off += xsnprintf(buf + off, len - off, "a");
! 102: if (off < len && flags & CMD_BIGDFLAG)
! 103: off += xsnprintf(buf + off, len - off, "D");
! 104: if (off < len && flags & CMD_DFLAG)
! 105: off += xsnprintf(buf + off, len - off, "d");
! 106: if (off < len && flags & CMD_GFLAG)
! 107: off += xsnprintf(buf + off, len - off, "g");
! 108: if (off < len && flags & CMD_KFLAG)
! 109: off += xsnprintf(buf + off, len - off, "k");
! 110: if (off < len && flags & CMD_UFLAG)
! 111: off += xsnprintf(buf + off, len - off, "u");
! 112: if (off < len && flags & CMD_BIGUFLAG)
! 113: off += xsnprintf(buf + off, len - off, "U");
! 114: return (off - boff);
! 115: }
! 116:
! 117: int
! 118: cmd_fill_argument(int flags, char **arg, int argc, char **argv)
! 119: {
! 120: *arg = NULL;
! 121:
! 122: if (flags & CMD_ARG1) {
! 123: if (argc != 1)
! 124: return (-1);
! 125: *arg = xstrdup(argv[0]);
! 126: return (0);
! 127: }
! 128:
! 129: if (flags & CMD_ARG01) {
! 130: if (argc != 0 && argc != 1)
! 131: return (-1);
! 132: if (argc == 1)
! 133: *arg = xstrdup(argv[0]);
! 134: return (0);
! 135: }
! 136:
! 137: if (argc != 0)
! 138: return (-1);
! 139: return (0);
! 140: }
! 141:
! 142: void
! 143: cmd_target_init(struct cmd *self, unused int key)
! 144: {
! 145: struct cmd_target_data *data;
! 146:
! 147: self->data = data = xmalloc(sizeof *data);
! 148: data->flags = 0;
! 149: data->target = NULL;
! 150: data->arg = NULL;
! 151: }
! 152:
! 153: int
! 154: cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
! 155: {
! 156: struct cmd_target_data *data;
! 157: int opt;
! 158:
! 159: /* Don't use the entry version since it may be dependent on key. */
! 160: cmd_target_init(self, 0);
! 161: data = self->data;
! 162:
! 163: while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
! 164: switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
! 165: case -1:
! 166: goto usage;
! 167: case 0:
! 168: continue;
! 169: }
! 170: switch (opt) {
! 171: case 't':
! 172: if (data->target == NULL)
! 173: data->target = xstrdup(optarg);
! 174: break;
! 175: default:
! 176: goto usage;
! 177: }
! 178: }
! 179: argc -= optind;
! 180: argv += optind;
! 181:
! 182: if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
! 183: goto usage;
! 184: return (0);
! 185:
! 186: usage:
! 187: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 188:
! 189: self->entry->free(self);
! 190: return (-1);
! 191: }
! 192:
! 193: void
! 194: cmd_target_send(struct cmd *self, struct buffer *b)
! 195: {
! 196: struct cmd_target_data *data = self->data;
! 197:
! 198: buffer_write(b, data, sizeof *data);
! 199: cmd_send_string(b, data->target);
! 200: cmd_send_string(b, data->arg);
! 201: }
! 202:
! 203: void
! 204: cmd_target_recv(struct cmd *self, struct buffer *b)
! 205: {
! 206: struct cmd_target_data *data;
! 207:
! 208: self->data = data = xmalloc(sizeof *data);
! 209: buffer_read(b, data, sizeof *data);
! 210: data->target = cmd_recv_string(b);
! 211: data->arg = cmd_recv_string(b);
! 212: }
! 213:
! 214: void
! 215: cmd_target_free(struct cmd *self)
! 216: {
! 217: struct cmd_target_data *data = self->data;
! 218:
! 219: if (data->target != NULL)
! 220: xfree(data->target);
! 221: if (data->arg != NULL)
! 222: xfree(data->arg);
! 223: xfree(data);
! 224: }
! 225:
! 226: size_t
! 227: cmd_target_print(struct cmd *self, char *buf, size_t len)
! 228: {
! 229: struct cmd_target_data *data = self->data;
! 230: size_t off = 0;
! 231:
! 232: off += xsnprintf(buf, len, "%s", self->entry->name);
! 233: if (data == NULL)
! 234: return (off);
! 235: off += cmd_print_flags(buf, len, off, data->flags);
! 236: if (off < len && data->target != NULL)
! 237: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 238: if (off < len && data->arg != NULL)
! 239: off += cmd_prarg(buf + off, len - off, " ", data->arg);
! 240: return (off);
! 241: }
! 242:
! 243: void
! 244: cmd_srcdst_init(struct cmd *self, unused int key)
! 245: {
! 246: struct cmd_srcdst_data *data;
! 247:
! 248: self->data = data = xmalloc(sizeof *data);
! 249: data->flags = 0;
! 250: data->src = NULL;
! 251: data->dst = NULL;
! 252: data->arg = NULL;
! 253: }
! 254:
! 255: int
! 256: cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
! 257: {
! 258: struct cmd_srcdst_data *data;
! 259: int opt;
! 260:
! 261: cmd_srcdst_init(self, 0);
! 262: data = self->data;
! 263:
! 264: while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) {
! 265: switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
! 266: case -1:
! 267: goto usage;
! 268: case 0:
! 269: continue;
! 270: }
! 271: switch (opt) {
! 272: case 's':
! 273: if (data->src == NULL)
! 274: data->src = xstrdup(optarg);
! 275: break;
! 276: case 't':
! 277: if (data->dst == NULL)
! 278: data->dst = xstrdup(optarg);
! 279: break;
! 280: default:
! 281: goto usage;
! 282: }
! 283: }
! 284: argc -= optind;
! 285: argv += optind;
! 286:
! 287: if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
! 288: goto usage;
! 289: return (0);
! 290:
! 291: usage:
! 292: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 293:
! 294: self->entry->free(self);
! 295: return (-1);
! 296: }
! 297:
! 298: void
! 299: cmd_srcdst_send(struct cmd *self, struct buffer *b)
! 300: {
! 301: struct cmd_srcdst_data *data = self->data;
! 302:
! 303: buffer_write(b, data, sizeof *data);
! 304: cmd_send_string(b, data->src);
! 305: cmd_send_string(b, data->dst);
! 306: cmd_send_string(b, data->arg);
! 307: }
! 308:
! 309: void
! 310: cmd_srcdst_recv(struct cmd *self, struct buffer *b)
! 311: {
! 312: struct cmd_srcdst_data *data;
! 313:
! 314: self->data = data = xmalloc(sizeof *data);
! 315: buffer_read(b, data, sizeof *data);
! 316: data->src = cmd_recv_string(b);
! 317: data->dst = cmd_recv_string(b);
! 318: data->arg = cmd_recv_string(b);
! 319: }
! 320:
! 321: void
! 322: cmd_srcdst_free(struct cmd *self)
! 323: {
! 324: struct cmd_srcdst_data *data = self->data;
! 325:
! 326: if (data->src != NULL)
! 327: xfree(data->src);
! 328: if (data->dst != NULL)
! 329: xfree(data->dst);
! 330: if (data->arg != NULL)
! 331: xfree(data->arg);
! 332: xfree(data);
! 333: }
! 334:
! 335: size_t
! 336: cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
! 337: {
! 338: struct cmd_srcdst_data *data = self->data;
! 339: size_t off = 0;
! 340:
! 341: off += xsnprintf(buf, len, "%s", self->entry->name);
! 342: if (data == NULL)
! 343: return (off);
! 344: off += cmd_print_flags(buf, len, off, data->flags);
! 345: if (off < len && data->src != NULL)
! 346: off += xsnprintf(buf + off, len - off, " -s %s", data->src);
! 347: if (off < len && data->dst != NULL)
! 348: off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
! 349: if (off < len && data->arg != NULL)
! 350: off += cmd_prarg(buf + off, len - off, " ", data->arg);
! 351: return (off);
! 352: }
! 353:
! 354: void
! 355: cmd_buffer_init(struct cmd *self, unused int key)
! 356: {
! 357: struct cmd_buffer_data *data;
! 358:
! 359: self->data = data = xmalloc(sizeof *data);
! 360: data->flags = 0;
! 361: data->target = NULL;
! 362: data->buffer = -1;
! 363: data->arg = NULL;
! 364: }
! 365:
! 366: int
! 367: cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
! 368: {
! 369: struct cmd_buffer_data *data;
! 370: int opt, n;
! 371: const char *errstr;
! 372:
! 373: cmd_buffer_init(self, 0);
! 374: data = self->data;
! 375:
! 376: while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) {
! 377: switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
! 378: case -1:
! 379: goto usage;
! 380: case 0:
! 381: continue;
! 382: }
! 383: switch (opt) {
! 384: case 'b':
! 385: if (data->buffer == -1) {
! 386: n = strtonum(optarg, 0, INT_MAX, &errstr);
! 387: if (errstr != NULL) {
! 388: xasprintf(cause, "buffer %s", errstr);
! 389: goto error;
! 390: }
! 391: data->buffer = n;
! 392: }
! 393: break;
! 394: case 't':
! 395: if (data->target == NULL)
! 396: data->target = xstrdup(optarg);
! 397: break;
! 398: default:
! 399: goto usage;
! 400: }
! 401: }
! 402: argc -= optind;
! 403: argv += optind;
! 404:
! 405: if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
! 406: goto usage;
! 407: return (0);
! 408:
! 409: usage:
! 410: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 411:
! 412: error:
! 413: self->entry->free(self);
! 414: return (-1);
! 415: }
! 416:
! 417: void
! 418: cmd_buffer_send(struct cmd *self, struct buffer *b)
! 419: {
! 420: struct cmd_buffer_data *data = self->data;
! 421:
! 422: buffer_write(b, data, sizeof *data);
! 423: cmd_send_string(b, data->target);
! 424: cmd_send_string(b, data->arg);
! 425: }
! 426:
! 427: void
! 428: cmd_buffer_recv(struct cmd *self, struct buffer *b)
! 429: {
! 430: struct cmd_buffer_data *data;
! 431:
! 432: self->data = data = xmalloc(sizeof *data);
! 433: buffer_read(b, data, sizeof *data);
! 434: data->target = cmd_recv_string(b);
! 435: data->arg = cmd_recv_string(b);
! 436: }
! 437:
! 438: void
! 439: cmd_buffer_free(struct cmd *self)
! 440: {
! 441: struct cmd_buffer_data *data = self->data;
! 442:
! 443: if (data->target != NULL)
! 444: xfree(data->target);
! 445: if (data->arg != NULL)
! 446: xfree(data->arg);
! 447: xfree(data);
! 448: }
! 449:
! 450: size_t
! 451: cmd_buffer_print(struct cmd *self, char *buf, size_t len)
! 452: {
! 453: struct cmd_buffer_data *data = self->data;
! 454: size_t off = 0;
! 455:
! 456: off += xsnprintf(buf, len, "%s", self->entry->name);
! 457: if (data == NULL)
! 458: return (off);
! 459: off += cmd_print_flags(buf, len, off, data->flags);
! 460: if (off < len && data->buffer != -1)
! 461: off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
! 462: if (off < len && data->target != NULL)
! 463: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 464: if (off < len && data->arg != NULL)
! 465: off += cmd_prarg(buf + off, len - off, " ", data->arg);
! 466: return (off);
! 467: }
! 468:
! 469: void
! 470: cmd_option_init(struct cmd *self, unused int key)
! 471: {
! 472: struct cmd_option_data *data;
! 473:
! 474: self->data = data = xmalloc(sizeof *data);
! 475: data->flags = 0;
! 476: data->target = NULL;
! 477: data->option = NULL;
! 478: data->value = NULL;
! 479: }
! 480:
! 481: int
! 482: cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause)
! 483: {
! 484: struct cmd_option_data *data;
! 485: int opt;
! 486:
! 487: /* Don't use the entry version since it may be dependent on key. */
! 488: cmd_option_init(self, 0);
! 489: data = self->data;
! 490:
! 491: while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
! 492: switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
! 493: case -1:
! 494: goto usage;
! 495: case 0:
! 496: continue;
! 497: }
! 498: switch (opt) {
! 499: case 't':
! 500: if (data->target == NULL)
! 501: data->target = xstrdup(optarg);
! 502: break;
! 503: default:
! 504: goto usage;
! 505: }
! 506: }
! 507: argc -= optind;
! 508: argv += optind;
! 509:
! 510: if (argc == 2) {
! 511: data->option = xstrdup(argv[0]);
! 512: data->value = xstrdup(argv[1]);
! 513: } else if (argc == 1)
! 514: data->option = xstrdup(argv[0]);
! 515: else
! 516: goto usage;
! 517: return (0);
! 518:
! 519: usage:
! 520: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 521:
! 522: self->entry->free(self);
! 523: return (-1);
! 524: }
! 525:
! 526: void
! 527: cmd_option_send(struct cmd *self, struct buffer *b)
! 528: {
! 529: struct cmd_option_data *data = self->data;
! 530:
! 531: buffer_write(b, data, sizeof *data);
! 532: cmd_send_string(b, data->target);
! 533: cmd_send_string(b, data->option);
! 534: cmd_send_string(b, data->value);
! 535: }
! 536:
! 537: void
! 538: cmd_option_recv(struct cmd *self, struct buffer *b)
! 539: {
! 540: struct cmd_option_data *data;
! 541:
! 542: self->data = data = xmalloc(sizeof *data);
! 543: buffer_read(b, data, sizeof *data);
! 544: data->target = cmd_recv_string(b);
! 545: data->option = cmd_recv_string(b);
! 546: data->value = cmd_recv_string(b);
! 547: }
! 548:
! 549: void
! 550: cmd_option_free(struct cmd *self)
! 551: {
! 552: struct cmd_option_data *data = self->data;
! 553:
! 554: if (data->target != NULL)
! 555: xfree(data->target);
! 556: if (data->option != NULL)
! 557: xfree(data->option);
! 558: if (data->value != NULL)
! 559: xfree(data->value);
! 560: xfree(data);
! 561: }
! 562:
! 563: size_t
! 564: cmd_option_print(struct cmd *self, char *buf, size_t len)
! 565: {
! 566: struct cmd_option_data *data = self->data;
! 567: size_t off = 0;
! 568:
! 569: off += xsnprintf(buf, len, "%s", self->entry->name);
! 570: if (data == NULL)
! 571: return (off);
! 572: off += cmd_print_flags(buf, len, off, data->flags);
! 573: if (off < len && data->target != NULL)
! 574: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 575: if (off < len && data->option != NULL)
! 576: off += xsnprintf(buf + off, len - off, " %s", data->option);
! 577: if (off < len && data->value != NULL)
! 578: off += xsnprintf(buf + off, len - off, " %s", data->value);
! 579: return (off);
! 580: }
! 581:
! 582: void
! 583: cmd_pane_init(struct cmd *self, unused int key)
! 584: {
! 585: struct cmd_pane_data *data;
! 586:
! 587: self->data = data = xmalloc(sizeof *data);
! 588: data->flags = 0;
! 589: data->target = NULL;
! 590: data->arg = NULL;
! 591: data->pane = -1;
! 592: }
! 593:
! 594: int
! 595: cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
! 596: {
! 597: struct cmd_pane_data *data;
! 598: int opt, n;
! 599: const char *errstr;
! 600:
! 601: /* Don't use the entry version since it may be dependent on key. */
! 602: cmd_pane_init(self, 0);
! 603: data = self->data;
! 604:
! 605: while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) {
! 606: switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
! 607: case -1:
! 608: goto usage;
! 609: case 0:
! 610: continue;
! 611: }
! 612: switch (opt) {
! 613: case 'p':
! 614: if (data->pane == -1) {
! 615: n = strtonum(optarg, 0, INT_MAX, &errstr);
! 616: if (errstr != NULL) {
! 617: xasprintf(cause, "pane %s", errstr);
! 618: goto error;
! 619: }
! 620: data->pane = n;
! 621: }
! 622: break;
! 623: case 't':
! 624: if (data->target == NULL)
! 625: data->target = xstrdup(optarg);
! 626: break;
! 627: default:
! 628: goto usage;
! 629: }
! 630: }
! 631: argc -= optind;
! 632: argv += optind;
! 633:
! 634: if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
! 635: goto usage;
! 636: return (0);
! 637:
! 638: usage:
! 639: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 640:
! 641: error:
! 642: self->entry->free(self);
! 643: return (-1);
! 644: }
! 645:
! 646: void
! 647: cmd_pane_send(struct cmd *self, struct buffer *b)
! 648: {
! 649: struct cmd_pane_data *data = self->data;
! 650:
! 651: buffer_write(b, data, sizeof *data);
! 652: cmd_send_string(b, data->target);
! 653: cmd_send_string(b, data->arg);
! 654: }
! 655:
! 656: void
! 657: cmd_pane_recv(struct cmd *self, struct buffer *b)
! 658: {
! 659: struct cmd_pane_data *data;
! 660:
! 661: self->data = data = xmalloc(sizeof *data);
! 662: buffer_read(b, data, sizeof *data);
! 663: data->target = cmd_recv_string(b);
! 664: data->arg = cmd_recv_string(b);
! 665: }
! 666:
! 667: void
! 668: cmd_pane_free(struct cmd *self)
! 669: {
! 670: struct cmd_pane_data *data = self->data;
! 671:
! 672: if (data->target != NULL)
! 673: xfree(data->target);
! 674: if (data->arg != NULL)
! 675: xfree(data->arg);
! 676: xfree(data);
! 677: }
! 678:
! 679: size_t
! 680: cmd_pane_print(struct cmd *self, char *buf, size_t len)
! 681: {
! 682: struct cmd_pane_data *data = self->data;
! 683: size_t off = 0;
! 684:
! 685: off += xsnprintf(buf, len, "%s", self->entry->name);
! 686: if (data == NULL)
! 687: return (off);
! 688: off += cmd_print_flags(buf, len, off, data->flags);
! 689: if (off < len && data->target != NULL)
! 690: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 691: if (off < len && data->arg != NULL)
! 692: off += cmd_prarg(buf + off, len - off, " ", data->arg);
! 693: return (off);
! 694: }