1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 5 #include <stdbool.h> 6 7 /* user defined includes */ 8 #include <linux/types.h> 9 #include <kvm/util.h> 10 #include <kvm/parse-options.h> 11 #include <kvm/strbuf.h> 12 13 #define OPT_SHORT 1 14 #define OPT_UNSET 2 15 16 static int opterror(const struct option *opt, const char *reason, int flags) 17 { 18 if (flags & OPT_SHORT) 19 return pr_error("switch `%c' %s", opt->short_name, reason); 20 if (flags & OPT_UNSET) 21 return pr_error("option `no-%s' %s", opt->long_name, reason); 22 return pr_error("option `%s' %s", opt->long_name, reason); 23 } 24 25 static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, 26 int flags, const char **arg) 27 { 28 if (p->opt) { 29 *arg = p->opt; 30 p->opt = NULL; 31 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || 32 **(p->argv + 1) == '-')) { 33 *arg = (const char *)opt->defval; 34 } else if (p->argc > 1) { 35 p->argc--; 36 *arg = *++p->argv; 37 } else 38 return opterror(opt, "requires a value", flags); 39 return 0; 40 } 41 42 #define numvalue(c) \ 43 ((c) >= 'a' ? (c) - 'a' + 10 : \ 44 (c) >= 'A' ? (c) - 'A' + 10 : (c) - '0') 45 46 static u64 readhex(const char *str, bool *error) 47 { 48 char *pos = strchr(str, 'x') + 1; 49 u64 res = 0; 50 51 while (*pos) { 52 unsigned int v = numvalue(*pos); 53 if (v > 16) { 54 *error = true; 55 return 0; 56 } 57 58 res = (res * 16) + v; 59 pos++; 60 } 61 62 *error = false; 63 return res; 64 } 65 66 static int readnum(const struct option *opt, int flags, 67 const char *str, char **end) 68 { 69 if (strchr(str, 'x')) { 70 bool error; 71 u64 value; 72 73 value = readhex(str, &error); 74 if (error) 75 goto enotnum; 76 77 switch (opt->type) { 78 case OPTION_INTEGER: 79 *(int *)opt->value = value; 80 break; 81 case OPTION_UINTEGER: 82 *(unsigned int *)opt->value = value; 83 break; 84 case OPTION_LONG: 85 *(long *)opt->value = value; 86 break; 87 case OPTION_U64: 88 *(u64 *)opt->value = value; 89 break; 90 default: 91 goto invcall; 92 } 93 } else { 94 switch (opt->type) { 95 case OPTION_INTEGER: 96 *(int *)opt->value = strtol(str, end, 10); 97 break; 98 case OPTION_UINTEGER: 99 *(unsigned int *)opt->value = strtol(str, end, 10); 100 break; 101 case OPTION_LONG: 102 *(long *)opt->value = strtol(str, end, 10); 103 break; 104 case OPTION_U64: 105 *(u64 *)opt->value = strtoull(str, end, 10); 106 break; 107 default: 108 goto invcall; 109 } 110 } 111 112 return 0; 113 114 enotnum: 115 return opterror(opt, "expects a numerical value", flags); 116 invcall: 117 return opterror(opt, "invalid numeric conversion", flags); 118 } 119 120 static int get_value(struct parse_opt_ctx_t *p, 121 const struct option *opt, int flags) 122 { 123 const char *s, *arg = NULL; 124 const int unset = flags & OPT_UNSET; 125 126 if (unset && p->opt) 127 return opterror(opt, "takes no value", flags); 128 if (unset && (opt->flags & PARSE_OPT_NONEG)) 129 return opterror(opt, "isn't available", flags); 130 131 if (!(flags & OPT_SHORT) && p->opt) { 132 switch (opt->type) { 133 case OPTION_CALLBACK: 134 if (!(opt->flags & PARSE_OPT_NOARG)) 135 break; 136 /* FALLTHROUGH */ 137 case OPTION_BOOLEAN: 138 case OPTION_INCR: 139 case OPTION_BIT: 140 case OPTION_SET_UINT: 141 case OPTION_SET_PTR: 142 return opterror(opt, "takes no value", flags); 143 case OPTION_END: 144 case OPTION_ARGUMENT: 145 case OPTION_GROUP: 146 case OPTION_STRING: 147 case OPTION_INTEGER: 148 case OPTION_UINTEGER: 149 case OPTION_LONG: 150 case OPTION_U64: 151 default: 152 break; 153 } 154 } 155 156 switch (opt->type) { 157 case OPTION_BIT: 158 if (unset) 159 *(int *)opt->value &= ~opt->defval; 160 else 161 *(int *)opt->value |= opt->defval; 162 return 0; 163 164 case OPTION_BOOLEAN: 165 *(bool *)opt->value = unset ? false : true; 166 return 0; 167 168 case OPTION_INCR: 169 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; 170 return 0; 171 172 case OPTION_SET_UINT: 173 *(unsigned int *)opt->value = unset ? 0 : opt->defval; 174 return 0; 175 176 case OPTION_SET_PTR: 177 *(void **)opt->value = unset ? NULL : (void *)opt->defval; 178 return 0; 179 180 case OPTION_STRING: 181 if (unset) 182 *(const char **)opt->value = NULL; 183 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 184 *(const char **)opt->value = (const char *)opt->defval; 185 else 186 return get_arg(p, opt, flags, 187 (const char **)opt->value); 188 return 0; 189 190 case OPTION_CALLBACK: 191 if (unset) 192 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; 193 if (opt->flags & PARSE_OPT_NOARG) 194 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 195 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 196 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 197 if (get_arg(p, opt, flags, &arg)) 198 return -1; 199 return (*opt->callback)(opt, arg, 0) ? (-1) : 0; 200 201 case OPTION_INTEGER: 202 if (unset) { 203 *(int *)opt->value = 0; 204 return 0; 205 } 206 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 207 *(int *)opt->value = opt->defval; 208 return 0; 209 } 210 if (get_arg(p, opt, flags, &arg)) 211 return -1; 212 return readnum(opt, flags, arg, (char **)&s); 213 214 case OPTION_UINTEGER: 215 if (unset) { 216 *(unsigned int *)opt->value = 0; 217 return 0; 218 } 219 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 220 *(unsigned int *)opt->value = opt->defval; 221 return 0; 222 } 223 if (get_arg(p, opt, flags, &arg)) 224 return -1; 225 return readnum(opt, flags, arg, (char **)&s); 226 227 case OPTION_LONG: 228 if (unset) { 229 *(long *)opt->value = 0; 230 return 0; 231 } 232 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 233 *(long *)opt->value = opt->defval; 234 return 0; 235 } 236 if (get_arg(p, opt, flags, &arg)) 237 return -1; 238 return readnum(opt, flags, arg, (char **)&s); 239 240 case OPTION_U64: 241 if (unset) { 242 *(u64 *)opt->value = 0; 243 return 0; 244 } 245 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 246 *(u64 *)opt->value = opt->defval; 247 return 0; 248 } 249 if (get_arg(p, opt, flags, &arg)) 250 return -1; 251 return readnum(opt, flags, arg, (char **)&s); 252 253 case OPTION_END: 254 case OPTION_ARGUMENT: 255 case OPTION_GROUP: 256 default: 257 die("should not happen, someone must be hit on the forehead"); 258 } 259 } 260 261 #define USAGE_OPTS_WIDTH 24 262 #define USAGE_GAP 2 263 264 static int usage_with_options_internal(const char * const *usagestr, 265 const struct option *opts, int full) 266 { 267 if (!usagestr) 268 return PARSE_OPT_HELP; 269 270 fprintf(stderr, "\n usage: %s\n", *usagestr++); 271 while (*usagestr && **usagestr) 272 fprintf(stderr, " or: %s\n", *usagestr++); 273 while (*usagestr) { 274 fprintf(stderr, "%s%s\n", 275 **usagestr ? " " : "", 276 *usagestr); 277 usagestr++; 278 } 279 280 if (opts->type != OPTION_GROUP) 281 fputc('\n', stderr); 282 283 for (; opts->type != OPTION_END; opts++) { 284 size_t pos; 285 int pad; 286 287 if (opts->type == OPTION_GROUP) { 288 fputc('\n', stderr); 289 if (*opts->help) 290 fprintf(stderr, "%s\n", opts->help); 291 continue; 292 } 293 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 294 continue; 295 296 pos = fprintf(stderr, " "); 297 if (opts->short_name) 298 pos += fprintf(stderr, "-%c", opts->short_name); 299 else 300 pos += fprintf(stderr, " "); 301 302 if (opts->long_name && opts->short_name) 303 pos += fprintf(stderr, ", "); 304 if (opts->long_name) 305 pos += fprintf(stderr, "--%s", opts->long_name); 306 307 switch (opts->type) { 308 case OPTION_ARGUMENT: 309 break; 310 case OPTION_LONG: 311 case OPTION_U64: 312 case OPTION_INTEGER: 313 case OPTION_UINTEGER: 314 if (opts->flags & PARSE_OPT_OPTARG) 315 if (opts->long_name) 316 pos += fprintf(stderr, "[=<n>]"); 317 else 318 pos += fprintf(stderr, "[<n>]"); 319 else 320 pos += fprintf(stderr, " <n>"); 321 break; 322 case OPTION_CALLBACK: 323 if (opts->flags & PARSE_OPT_NOARG) 324 break; 325 /* FALLTHROUGH */ 326 case OPTION_STRING: 327 if (opts->argh) { 328 if (opts->flags & PARSE_OPT_OPTARG) 329 if (opts->long_name) 330 pos += fprintf(stderr, "[=<%s>]", opts->argh); 331 else 332 pos += fprintf(stderr, "[<%s>]", opts->argh); 333 else 334 pos += fprintf(stderr, " <%s>", opts->argh); 335 } else { 336 if (opts->flags & PARSE_OPT_OPTARG) 337 if (opts->long_name) 338 pos += fprintf(stderr, "[=...]"); 339 else 340 pos += fprintf(stderr, "[...]"); 341 else 342 pos += fprintf(stderr, " ..."); 343 } 344 break; 345 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ 346 case OPTION_END: 347 case OPTION_GROUP: 348 case OPTION_BIT: 349 case OPTION_BOOLEAN: 350 case OPTION_INCR: 351 case OPTION_SET_UINT: 352 case OPTION_SET_PTR: 353 break; 354 } 355 if (pos <= USAGE_OPTS_WIDTH) 356 pad = USAGE_OPTS_WIDTH - pos; 357 else { 358 fputc('\n', stderr); 359 pad = USAGE_OPTS_WIDTH; 360 } 361 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 362 } 363 fputc('\n', stderr); 364 365 return PARSE_OPT_HELP; 366 } 367 368 void usage_with_options(const char * const *usagestr, 369 const struct option *opts) 370 { 371 usage_with_options_internal(usagestr, opts, 0); 372 exit(129); 373 } 374 375 static void check_typos(const char *arg, const struct option *options) 376 { 377 if (strlen(arg) < 3) 378 return; 379 380 if (!prefixcmp(arg, "no-")) { 381 pr_error ("did you mean `--%s` (with two dashes ?)", arg); 382 exit(129); 383 } 384 385 for (; options->type != OPTION_END; options++) { 386 if (!options->long_name) 387 continue; 388 if (!prefixcmp(options->long_name, arg)) { 389 pr_error ("did you mean `--%s` (with two dashes ?)", arg); 390 exit(129); 391 } 392 } 393 } 394 395 static int parse_options_usage(const char * const *usagestr, 396 const struct option *opts) 397 { 398 return usage_with_options_internal(usagestr, opts, 0); 399 } 400 401 static int parse_short_opt(struct parse_opt_ctx_t *p, 402 const struct option *options) 403 { 404 for (; options->type != OPTION_END; options++) { 405 if (options->short_name == *p->opt) { 406 p->opt = p->opt[1] ? p->opt + 1 : NULL; 407 return get_value(p, options, OPT_SHORT); 408 } 409 } 410 return -2; 411 } 412 413 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, 414 const struct option *options) 415 { 416 const char *arg_end = strchr(arg, '='); 417 const struct option *abbrev_option = NULL, *ambiguous_option = NULL; 418 int abbrev_flags = 0, ambiguous_flags = 0; 419 420 if (!arg_end) 421 arg_end = arg + strlen(arg); 422 423 for (; options->type != OPTION_END; options++) { 424 const char *rest; 425 int flags = 0; 426 427 if (!options->long_name) 428 continue; 429 430 rest = skip_prefix(arg, options->long_name); 431 if (options->type == OPTION_ARGUMENT) { 432 if (!rest) 433 continue; 434 if (*rest == '=') 435 return opterror(options, "takes no value", 436 flags); 437 if (*rest) 438 continue; 439 p->out[p->cpidx++] = arg - 2; 440 return 0; 441 } 442 if (!rest) { 443 /* abbreviated? */ 444 if (!strncmp(options->long_name, arg, arg_end - arg)) { 445 is_abbreviated: 446 if (abbrev_option) { 447 /* 448 * If this is abbreviated, it is 449 * ambiguous. So when there is no 450 * exact match later, we need to 451 * error out. 452 */ 453 ambiguous_option = abbrev_option; 454 ambiguous_flags = abbrev_flags; 455 } 456 if (!(flags & OPT_UNSET) && *arg_end) 457 p->opt = arg_end + 1; 458 abbrev_option = options; 459 abbrev_flags = flags; 460 continue; 461 } 462 /* negated and abbreviated very much? */ 463 if (!prefixcmp("no-", arg)) { 464 flags |= OPT_UNSET; 465 goto is_abbreviated; 466 } 467 /* negated? */ 468 if (strncmp(arg, "no-", 3)) 469 continue; 470 flags |= OPT_UNSET; 471 rest = skip_prefix(arg + 3, options->long_name); 472 /* abbreviated and negated? */ 473 if (!rest && !prefixcmp(options->long_name, arg + 3)) 474 goto is_abbreviated; 475 if (!rest) 476 continue; 477 } 478 if (*rest) { 479 if (*rest != '=') 480 continue; 481 p->opt = rest + 1; 482 } 483 return get_value(p, options, flags); 484 } 485 486 if (ambiguous_option) 487 return pr_error("Ambiguous option: %s " 488 "(could be --%s%s or --%s%s)", 489 arg, 490 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 491 ambiguous_option->long_name, 492 (abbrev_flags & OPT_UNSET) ? "no-" : "", 493 abbrev_option->long_name); 494 if (abbrev_option) 495 return get_value(p, abbrev_option, abbrev_flags); 496 return -2; 497 } 498 499 500 static void parse_options_start(struct parse_opt_ctx_t *ctx, int argc, 501 const char **argv, int flags) 502 { 503 memset(ctx, 0, sizeof(*ctx)); 504 ctx->argc = argc; 505 ctx->argv = argv; 506 ctx->out = argv; 507 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); 508 ctx->flags = flags; 509 if ((flags & PARSE_OPT_KEEP_UNKNOWN) && 510 (flags & PARSE_OPT_STOP_AT_NON_OPTION)) 511 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); 512 } 513 514 static int parse_options_end(struct parse_opt_ctx_t *ctx) 515 { 516 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); 517 ctx->out[ctx->cpidx + ctx->argc] = NULL; 518 return ctx->cpidx + ctx->argc; 519 } 520 521 522 static int parse_options_step(struct parse_opt_ctx_t *ctx, 523 const struct option *options, const char * const usagestr[]) 524 { 525 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 526 527 /* we must reset ->opt, unknown short option leave it dangling */ 528 ctx->opt = NULL; 529 530 for (; ctx->argc; ctx->argc--, ctx->argv++) { 531 const char *arg = ctx->argv[0]; 532 533 if (*arg != '-' || !arg[1]) { 534 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 535 break; 536 ctx->out[ctx->cpidx++] = ctx->argv[0]; 537 continue; 538 } 539 540 if (arg[1] != '-') { 541 ctx->opt = arg + 1; 542 if (internal_help && *ctx->opt == 'h') 543 return parse_options_usage(usagestr, options); 544 switch (parse_short_opt(ctx, options)) { 545 case -1: 546 return parse_options_usage(usagestr, options); 547 case -2: 548 goto unknown; 549 default: 550 break; 551 } 552 if (ctx->opt) 553 check_typos(arg + 1, options); 554 while (ctx->opt) { 555 if (internal_help && *ctx->opt == 'h') 556 return parse_options_usage(usagestr, 557 options); 558 switch (parse_short_opt(ctx, options)) { 559 case -1: 560 return parse_options_usage(usagestr, 561 options); 562 case -2: 563 /* fake a short option thing to hide 564 * the fact that we may have 565 * started to parse aggregated stuff 566 * 567 * This is leaky, too bad. 568 */ 569 ctx->argv[0] = strdup(ctx->opt - 1); 570 *(char *)ctx->argv[0] = '-'; 571 goto unknown; 572 default: 573 break; 574 } 575 } 576 continue; 577 } 578 579 if (!arg[2]) { /* "--" */ 580 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { 581 ctx->argc--; 582 ctx->argv++; 583 } 584 break; 585 } 586 587 if (internal_help && !strcmp(arg + 2, "help-all")) 588 return usage_with_options_internal(usagestr, options, 589 1); 590 if (internal_help && !strcmp(arg + 2, "help")) 591 return parse_options_usage(usagestr, options); 592 switch (parse_long_opt(ctx, arg + 2, options)) { 593 case -1: 594 return parse_options_usage(usagestr, options); 595 case -2: 596 goto unknown; 597 default: 598 break; 599 } 600 continue; 601 unknown: 602 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) 603 return PARSE_OPT_UNKNOWN; 604 ctx->out[ctx->cpidx++] = ctx->argv[0]; 605 ctx->opt = NULL; 606 } 607 return PARSE_OPT_DONE; 608 } 609 610 int parse_options(int argc, const char **argv, const struct option *options, 611 const char * const usagestr[], int flags) 612 { 613 struct parse_opt_ctx_t ctx; 614 615 parse_options_start(&ctx, argc, argv, flags); 616 switch (parse_options_step(&ctx, options, usagestr)) { 617 case PARSE_OPT_HELP: 618 exit(129); 619 case PARSE_OPT_DONE: 620 break; 621 default: /* PARSE_OPT_UNKNOWN */ 622 if (ctx.argv[0][1] == '-') { 623 pr_error("unknown option `%s'", ctx.argv[0] + 2); 624 } else { 625 pr_error("unknown switch `%c'", *ctx.opt); 626 } 627 usage_with_options(usagestr, options); 628 } 629 630 return parse_options_end(&ctx); 631 } 632