1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/compiler.h> 3 #include <linux/string.h> 4 #include <linux/types.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <ctype.h> 10 #include "subcmd-util.h" 11 #include "parse-options.h" 12 #include "subcmd-config.h" 13 #include "pager.h" 14 15 #define OPT_SHORT 1 16 #define OPT_UNSET 2 17 18 char *error_buf; 19 20 static int opterror(const struct option *opt, const char *reason, int flags) 21 { 22 if (flags & OPT_SHORT) 23 fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason); 24 else if (flags & OPT_UNSET) 25 fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason); 26 else 27 fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason); 28 29 return -1; 30 } 31 32 static const char *skip_prefix(const char *str, const char *prefix) 33 { 34 size_t len = strlen(prefix); 35 return strncmp(str, prefix, len) ? NULL : str + len; 36 } 37 38 static void optwarning(const struct option *opt, const char *reason, int flags) 39 { 40 if (flags & OPT_SHORT) 41 fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason); 42 else if (flags & OPT_UNSET) 43 fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason); 44 else 45 fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason); 46 } 47 48 static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, 49 int flags, const char **arg) 50 { 51 const char *res; 52 53 if (p->opt) { 54 res = p->opt; 55 p->opt = NULL; 56 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || 57 **(p->argv + 1) == '-')) { 58 res = (const char *)opt->defval; 59 } else if (p->argc > 1) { 60 p->argc--; 61 res = *++p->argv; 62 } else 63 return opterror(opt, "requires a value", flags); 64 if (arg) 65 *arg = res; 66 return 0; 67 } 68 69 static int get_value(struct parse_opt_ctx_t *p, 70 const struct option *opt, int flags) 71 { 72 const char *s, *arg = NULL; 73 const int unset = flags & OPT_UNSET; 74 int err; 75 bool force_defval = false; 76 77 if (unset && p->opt) 78 return opterror(opt, "takes no value", flags); 79 if (unset && (opt->flags & PARSE_OPT_NONEG)) 80 return opterror(opt, "isn't available", flags); 81 if (opt->flags & PARSE_OPT_DISABLED) 82 return opterror(opt, "is not usable", flags); 83 84 if (opt->flags & PARSE_OPT_EXCLUSIVE) { 85 if (p->excl_opt && p->excl_opt != opt) { 86 char msg[128]; 87 88 if (((flags & OPT_SHORT) && p->excl_opt->short_name) || 89 p->excl_opt->long_name == NULL) { 90 snprintf(msg, sizeof(msg), "cannot be used with switch `%c'", 91 p->excl_opt->short_name); 92 } else { 93 snprintf(msg, sizeof(msg), "cannot be used with %s", 94 p->excl_opt->long_name); 95 } 96 opterror(opt, msg, flags); 97 return -3; 98 } 99 p->excl_opt = opt; 100 } 101 if (!(flags & OPT_SHORT) && p->opt) { 102 switch (opt->type) { 103 case OPTION_CALLBACK: 104 if (!(opt->flags & PARSE_OPT_NOARG)) 105 break; 106 /* FALLTHROUGH */ 107 case OPTION_BOOLEAN: 108 case OPTION_INCR: 109 case OPTION_BIT: 110 case OPTION_SET_UINT: 111 case OPTION_SET_PTR: 112 return opterror(opt, "takes no value", flags); 113 case OPTION_END: 114 case OPTION_ARGUMENT: 115 case OPTION_GROUP: 116 case OPTION_STRING: 117 case OPTION_INTEGER: 118 case OPTION_UINTEGER: 119 case OPTION_LONG: 120 case OPTION_ULONG: 121 case OPTION_U64: 122 default: 123 break; 124 } 125 } 126 127 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 128 if (!(p->flags & PARSE_OPT_OPTARG_ALLOW_NEXT)) { 129 /* 130 * If the option has an optional argument, and the argument is not 131 * provided in the option itself, do not attempt to get it from 132 * the next argument, unless PARSE_OPT_OPTARG_ALLOW_NEXT is set. 133 * 134 * This prevents a non-option argument from being interpreted as an 135 * optional argument of a preceding option, for example: 136 * 137 * $ cmd --opt val 138 * -> is "val" argument of "--opt" or a separate non-option 139 * argument? 140 * 141 * With PARSE_OPT_OPTARG_ALLOW_NEXT, "val" is interpreted as 142 * the argument of "--opt", i.e. the same as "--opt=val". 143 * Without PARSE_OPT_OPTARG_ALLOW_NEXT, --opt is interpreted 144 * as having the default value, and "val" as a separate non-option 145 * argument. 146 * 147 * PARSE_OPT_OPTARG_ALLOW_NEXT is useful for commands that take no 148 * non-option arguments and want to allow more flexibility in 149 * optional argument passing. 150 */ 151 force_defval = true; 152 } 153 154 if (p->argc <= 1 || p->argv[1][0] == '-') { 155 /* 156 * If next argument is an option or does not exist, 157 * use the default value. 158 */ 159 force_defval = true; 160 } 161 } 162 163 if (opt->flags & PARSE_OPT_NOBUILD) { 164 char reason[128]; 165 bool noarg = false; 166 167 err = snprintf(reason, sizeof(reason), 168 opt->flags & PARSE_OPT_CANSKIP ? 169 "is being ignored because %s " : 170 "is not available because %s", 171 opt->build_opt); 172 reason[sizeof(reason) - 1] = '\0'; 173 174 if (err < 0) 175 strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ? 176 "is being ignored" : 177 "is not available", 178 sizeof(reason)); 179 180 if (!(opt->flags & PARSE_OPT_CANSKIP)) 181 return opterror(opt, reason, flags); 182 183 err = 0; 184 if (unset) 185 noarg = true; 186 if (opt->flags & PARSE_OPT_NOARG) 187 noarg = true; 188 if (force_defval) 189 noarg = true; 190 191 switch (opt->type) { 192 case OPTION_BOOLEAN: 193 case OPTION_INCR: 194 case OPTION_BIT: 195 case OPTION_SET_UINT: 196 case OPTION_SET_PTR: 197 case OPTION_END: 198 case OPTION_ARGUMENT: 199 case OPTION_GROUP: 200 noarg = true; 201 break; 202 case OPTION_CALLBACK: 203 case OPTION_STRING: 204 case OPTION_INTEGER: 205 case OPTION_UINTEGER: 206 case OPTION_LONG: 207 case OPTION_ULONG: 208 case OPTION_U64: 209 default: 210 break; 211 } 212 213 if (!noarg) 214 err = get_arg(p, opt, flags, NULL); 215 if (err) 216 return err; 217 218 optwarning(opt, reason, flags); 219 return 0; 220 } 221 222 switch (opt->type) { 223 case OPTION_BIT: 224 if (unset) 225 *(int *)opt->value &= ~opt->defval; 226 else 227 *(int *)opt->value |= opt->defval; 228 return 0; 229 230 case OPTION_BOOLEAN: 231 *(bool *)opt->value = unset ? false : true; 232 if (opt->set) 233 *(bool *)opt->set = true; 234 return 0; 235 236 case OPTION_INCR: 237 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; 238 return 0; 239 240 case OPTION_SET_UINT: 241 *(unsigned int *)opt->value = unset ? 0 : opt->defval; 242 return 0; 243 244 case OPTION_SET_PTR: 245 *(void **)opt->value = unset ? NULL : (void *)opt->defval; 246 return 0; 247 248 case OPTION_STRING: 249 err = 0; 250 if (unset) 251 *(const char **)opt->value = NULL; 252 else if (force_defval) 253 *(const char **)opt->value = (const char *)opt->defval; 254 else 255 err = get_arg(p, opt, flags, (const char **)opt->value); 256 257 if (opt->set) 258 *(bool *)opt->set = true; 259 260 /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ 261 if (opt->flags & PARSE_OPT_NOEMPTY) { 262 const char *val = *(const char **)opt->value; 263 264 if (!val) 265 return err; 266 267 /* Similar to unset if we are given an empty string. */ 268 if (val[0] == '\0') { 269 *(const char **)opt->value = NULL; 270 return 0; 271 } 272 } 273 274 return err; 275 276 case OPTION_CALLBACK: 277 if (opt->set) 278 *(bool *)opt->set = true; 279 280 if (unset) 281 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; 282 if (opt->flags & PARSE_OPT_NOARG) 283 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 284 if (force_defval) 285 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 286 if (get_arg(p, opt, flags, &arg)) 287 return -1; 288 return (*opt->callback)(opt, arg, 0) ? (-1) : 0; 289 290 case OPTION_INTEGER: 291 if (unset) { 292 *(int *)opt->value = 0; 293 return 0; 294 } 295 if (force_defval) { 296 *(int *)opt->value = opt->defval; 297 return 0; 298 } 299 if (get_arg(p, opt, flags, &arg)) 300 return -1; 301 *(int *)opt->value = strtol(arg, (char **)&s, 10); 302 if (*s) 303 return opterror(opt, "expects a numerical value", flags); 304 return 0; 305 306 case OPTION_UINTEGER: 307 if (unset) { 308 *(unsigned int *)opt->value = 0; 309 return 0; 310 } 311 if (force_defval) { 312 *(unsigned int *)opt->value = opt->defval; 313 return 0; 314 } 315 if (get_arg(p, opt, flags, &arg)) 316 return -1; 317 if (arg[0] == '-') 318 return opterror(opt, "expects an unsigned numerical value", flags); 319 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); 320 if (*s) 321 return opterror(opt, "expects a numerical value", flags); 322 return 0; 323 324 case OPTION_LONG: 325 if (unset) { 326 *(long *)opt->value = 0; 327 return 0; 328 } 329 if (force_defval) { 330 *(long *)opt->value = opt->defval; 331 return 0; 332 } 333 if (get_arg(p, opt, flags, &arg)) 334 return -1; 335 *(long *)opt->value = strtol(arg, (char **)&s, 10); 336 if (*s) 337 return opterror(opt, "expects a numerical value", flags); 338 return 0; 339 340 case OPTION_ULONG: 341 if (unset) { 342 *(unsigned long *)opt->value = 0; 343 return 0; 344 } 345 if (force_defval) { 346 *(unsigned long *)opt->value = opt->defval; 347 return 0; 348 } 349 if (get_arg(p, opt, flags, &arg)) 350 return -1; 351 *(unsigned long *)opt->value = strtoul(arg, (char **)&s, 10); 352 if (*s) 353 return opterror(opt, "expects a numerical value", flags); 354 return 0; 355 356 case OPTION_U64: 357 if (unset) { 358 *(u64 *)opt->value = 0; 359 return 0; 360 } 361 if (force_defval) { 362 *(u64 *)opt->value = opt->defval; 363 return 0; 364 } 365 if (get_arg(p, opt, flags, &arg)) 366 return -1; 367 if (arg[0] == '-') 368 return opterror(opt, "expects an unsigned numerical value", flags); 369 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); 370 if (*s) 371 return opterror(opt, "expects a numerical value", flags); 372 return 0; 373 374 case OPTION_END: 375 case OPTION_ARGUMENT: 376 case OPTION_GROUP: 377 default: 378 die("should not happen, someone must be hit on the forehead"); 379 } 380 } 381 382 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) 383 { 384 retry: 385 for (; options->type != OPTION_END; options++) { 386 if (options->short_name == *p->opt) { 387 p->opt = p->opt[1] ? p->opt + 1 : NULL; 388 return get_value(p, options, OPT_SHORT); 389 } 390 } 391 392 if (options->parent) { 393 options = options->parent; 394 goto retry; 395 } 396 397 return -2; 398 } 399 400 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, 401 const struct option *options) 402 { 403 const char *arg_end = strchr(arg, '='); 404 const struct option *abbrev_option = NULL, *ambiguous_option = NULL; 405 int abbrev_flags = 0, ambiguous_flags = 0; 406 407 if (!arg_end) 408 arg_end = arg + strlen(arg); 409 410 retry: 411 for (; options->type != OPTION_END; options++) { 412 const char *rest; 413 int flags = 0; 414 415 if (!options->long_name) 416 continue; 417 418 rest = skip_prefix(arg, options->long_name); 419 if (options->type == OPTION_ARGUMENT) { 420 if (!rest) 421 continue; 422 if (*rest == '=') 423 return opterror(options, "takes no value", flags); 424 if (*rest) 425 continue; 426 p->out[p->cpidx++] = arg - 2; 427 return 0; 428 } 429 if (!rest) { 430 if (strstarts(options->long_name, "no-") && 431 !(options->flags & PARSE_OPT_NOAUTONEG)) { 432 /* 433 * The long name itself starts with "no-", so 434 * accept the option without "no-" so that users 435 * do not have to enter "no-no-" to get the 436 * negation. 437 */ 438 rest = skip_prefix(arg, options->long_name + 3); 439 if (rest) { 440 flags |= OPT_UNSET; 441 goto match; 442 } 443 /* Abbreviated case */ 444 if (strstarts(options->long_name + 3, arg)) { 445 flags |= OPT_UNSET; 446 goto is_abbreviated; 447 } 448 } 449 /* abbreviated? */ 450 if (!strncmp(options->long_name, arg, arg_end - arg)) { 451 is_abbreviated: 452 if (abbrev_option) { 453 /* 454 * If this is abbreviated, it is 455 * ambiguous. So when there is no 456 * exact match later, we need to 457 * error out. 458 */ 459 ambiguous_option = abbrev_option; 460 ambiguous_flags = abbrev_flags; 461 } 462 if (!(flags & OPT_UNSET) && *arg_end) 463 p->opt = arg_end + 1; 464 abbrev_option = options; 465 abbrev_flags = flags; 466 continue; 467 } 468 /* negated and abbreviated very much? */ 469 if (strstarts("no-", arg) && !(options->flags & PARSE_OPT_NOAUTONEG)) { 470 flags |= OPT_UNSET; 471 goto is_abbreviated; 472 } 473 /* negated? */ 474 if (strncmp(arg, "no-", 3) || (options->flags & PARSE_OPT_NOAUTONEG)) 475 continue; 476 flags |= OPT_UNSET; 477 rest = skip_prefix(arg + 3, options->long_name); 478 /* abbreviated and negated? */ 479 if (!rest && strstarts(options->long_name, arg + 3)) 480 goto is_abbreviated; 481 if (!rest) 482 continue; 483 } 484 match: 485 if (*rest) { 486 if (*rest != '=') 487 continue; 488 p->opt = rest + 1; 489 } 490 return get_value(p, options, flags); 491 } 492 493 if (ambiguous_option) { 494 fprintf(stderr, 495 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)\n", 496 arg, 497 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 498 ambiguous_option->long_name, 499 (abbrev_flags & OPT_UNSET) ? "no-" : "", 500 abbrev_option->long_name); 501 return -1; 502 } 503 if (abbrev_option) 504 return get_value(p, abbrev_option, abbrev_flags); 505 506 if (options->parent) { 507 options = options->parent; 508 goto retry; 509 } 510 511 return -2; 512 } 513 514 static void check_typos(const char *arg, const struct option *options) 515 { 516 if (strlen(arg) < 3) 517 return; 518 519 if (strstarts(arg, "no-")) { 520 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg); 521 exit(129); 522 } 523 524 for (; options->type != OPTION_END; options++) { 525 if (!options->long_name) 526 continue; 527 if (strstarts(options->long_name, arg)) { 528 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg); 529 exit(129); 530 } 531 } 532 } 533 534 static void parse_options_start(struct parse_opt_ctx_t *ctx, 535 int argc, const char **argv, int flags) 536 { 537 memset(ctx, 0, sizeof(*ctx)); 538 ctx->argc = argc - 1; 539 ctx->argv = argv + 1; 540 ctx->out = argv; 541 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); 542 ctx->flags = flags; 543 if ((flags & PARSE_OPT_KEEP_UNKNOWN) && 544 (flags & PARSE_OPT_STOP_AT_NON_OPTION)) 545 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); 546 } 547 548 static int usage_with_options_internal(const char * const *, 549 const struct option *, int, 550 struct parse_opt_ctx_t *); 551 552 static int parse_options_step(struct parse_opt_ctx_t *ctx, 553 const struct option *options, 554 const char * const usagestr[]) 555 { 556 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 557 int excl_short_opt = 1; 558 const char *arg; 559 560 /* we must reset ->opt, unknown short option leave it dangling */ 561 ctx->opt = NULL; 562 563 for (; ctx->argc; ctx->argc--, ctx->argv++) { 564 arg = ctx->argv[0]; 565 if (*arg != '-' || !arg[1]) { 566 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 567 break; 568 ctx->out[ctx->cpidx++] = ctx->argv[0]; 569 continue; 570 } 571 572 if (arg[1] != '-') { 573 ctx->opt = ++arg; 574 if (internal_help && *ctx->opt == 'h') { 575 return usage_with_options_internal(usagestr, options, 0, ctx); 576 } 577 switch (parse_short_opt(ctx, options)) { 578 case -1: 579 return parse_options_usage(usagestr, options, arg, 1); 580 case -2: 581 goto unknown; 582 case -3: 583 goto exclusive; 584 default: 585 break; 586 } 587 if (ctx->opt) 588 check_typos(arg, options); 589 while (ctx->opt) { 590 if (internal_help && *ctx->opt == 'h') 591 return usage_with_options_internal(usagestr, options, 0, ctx); 592 arg = ctx->opt; 593 switch (parse_short_opt(ctx, options)) { 594 case -1: 595 return parse_options_usage(usagestr, options, arg, 1); 596 case -2: 597 /* fake a short option thing to hide the fact that we may have 598 * started to parse aggregated stuff 599 * 600 * This is leaky, too bad. 601 */ 602 ctx->argv[0] = strdup(ctx->opt - 1); 603 *(char *)ctx->argv[0] = '-'; 604 goto unknown; 605 case -3: 606 goto exclusive; 607 default: 608 break; 609 } 610 } 611 continue; 612 } 613 614 if (!arg[2]) { /* "--" */ 615 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { 616 ctx->argc--; 617 ctx->argv++; 618 } 619 break; 620 } 621 622 arg += 2; 623 if (internal_help && !strcmp(arg, "help-all")) 624 return usage_with_options_internal(usagestr, options, 1, ctx); 625 if (internal_help && !strcmp(arg, "help")) 626 return usage_with_options_internal(usagestr, options, 0, ctx); 627 if (!strcmp(arg, "list-opts")) 628 return PARSE_OPT_LIST_OPTS; 629 if (!strcmp(arg, "list-cmds")) 630 return PARSE_OPT_LIST_SUBCMDS; 631 switch (parse_long_opt(ctx, arg, options)) { 632 case -1: 633 return parse_options_usage(usagestr, options, arg, 0); 634 case -2: 635 goto unknown; 636 case -3: 637 excl_short_opt = 0; 638 goto exclusive; 639 default: 640 break; 641 } 642 continue; 643 unknown: 644 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) 645 return PARSE_OPT_UNKNOWN; 646 ctx->out[ctx->cpidx++] = ctx->argv[0]; 647 ctx->opt = NULL; 648 } 649 return PARSE_OPT_DONE; 650 651 exclusive: 652 parse_options_usage(usagestr, options, arg, excl_short_opt); 653 if ((excl_short_opt && ctx->excl_opt->short_name) || 654 ctx->excl_opt->long_name == NULL) { 655 char opt = ctx->excl_opt->short_name; 656 parse_options_usage(NULL, options, &opt, 1); 657 } else { 658 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0); 659 } 660 return PARSE_OPT_HELP; 661 } 662 663 static int parse_options_end(struct parse_opt_ctx_t *ctx) 664 { 665 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); 666 ctx->out[ctx->cpidx + ctx->argc] = NULL; 667 return ctx->cpidx + ctx->argc; 668 } 669 670 int parse_options_subcommand(int argc, const char **argv, const struct option *options, 671 const char *const subcommands[], const char *usagestr[], int flags) 672 { 673 struct parse_opt_ctx_t ctx; 674 675 /* build usage string if it's not provided */ 676 if (subcommands && !usagestr[0]) { 677 char *buf = NULL; 678 679 astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]); 680 681 for (int i = 0; subcommands[i]; i++) { 682 if (i) 683 astrcat(&buf, "|"); 684 astrcat(&buf, subcommands[i]); 685 } 686 astrcat(&buf, "}"); 687 688 usagestr[0] = buf; 689 } 690 691 parse_options_start(&ctx, argc, argv, flags); 692 switch (parse_options_step(&ctx, options, usagestr)) { 693 case PARSE_OPT_HELP: 694 exit(129); 695 case PARSE_OPT_DONE: 696 break; 697 case PARSE_OPT_LIST_OPTS: 698 while (options->type != OPTION_END) { 699 if (options->long_name) 700 printf("--%s ", options->long_name); 701 options++; 702 } 703 putchar('\n'); 704 exit(130); 705 case PARSE_OPT_LIST_SUBCMDS: 706 if (subcommands) { 707 for (int i = 0; subcommands[i]; i++) 708 printf("%s ", subcommands[i]); 709 } 710 putchar('\n'); 711 exit(130); 712 default: /* PARSE_OPT_UNKNOWN */ 713 if (ctx.argv[0][1] == '-') 714 astrcatf(&error_buf, "unknown option `%s'", 715 ctx.argv[0] + 2); 716 else 717 astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt); 718 usage_with_options(usagestr, options); 719 } 720 721 return parse_options_end(&ctx); 722 } 723 724 int parse_options(int argc, const char **argv, const struct option *options, 725 const char * const usagestr[], int flags) 726 { 727 return parse_options_subcommand(argc, argv, options, NULL, 728 (const char **) usagestr, flags); 729 } 730 731 #define USAGE_OPTS_WIDTH 24 732 #define USAGE_GAP 2 733 734 static void print_option_help(const struct option *opts, int full) 735 { 736 size_t pos; 737 int pad; 738 739 if (opts->type == OPTION_GROUP) { 740 fputc('\n', stderr); 741 if (*opts->help) 742 fprintf(stderr, "%s\n", opts->help); 743 return; 744 } 745 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 746 return; 747 if (opts->flags & PARSE_OPT_DISABLED) 748 return; 749 750 pos = fprintf(stderr, " "); 751 if (opts->short_name) 752 pos += fprintf(stderr, "-%c", opts->short_name); 753 else 754 pos += fprintf(stderr, " "); 755 756 if (opts->long_name && opts->short_name) 757 pos += fprintf(stderr, ", "); 758 if (opts->long_name) 759 pos += fprintf(stderr, "--%s", opts->long_name); 760 761 switch (opts->type) { 762 case OPTION_ARGUMENT: 763 break; 764 case OPTION_LONG: 765 case OPTION_ULONG: 766 case OPTION_U64: 767 case OPTION_INTEGER: 768 case OPTION_UINTEGER: 769 if (opts->flags & PARSE_OPT_OPTARG) 770 if (opts->long_name) 771 pos += fprintf(stderr, "[=<n>]"); 772 else 773 pos += fprintf(stderr, "[<n>]"); 774 else 775 pos += fprintf(stderr, " <n>"); 776 break; 777 case OPTION_CALLBACK: 778 if (opts->flags & PARSE_OPT_NOARG) 779 break; 780 /* FALLTHROUGH */ 781 case OPTION_STRING: 782 if (opts->argh) { 783 if (opts->flags & PARSE_OPT_OPTARG) 784 if (opts->long_name) 785 pos += fprintf(stderr, "[=<%s>]", opts->argh); 786 else 787 pos += fprintf(stderr, "[<%s>]", opts->argh); 788 else 789 pos += fprintf(stderr, " <%s>", opts->argh); 790 } else { 791 if (opts->flags & PARSE_OPT_OPTARG) 792 if (opts->long_name) 793 pos += fprintf(stderr, "[=...]"); 794 else 795 pos += fprintf(stderr, "[...]"); 796 else 797 pos += fprintf(stderr, " ..."); 798 } 799 break; 800 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ 801 case OPTION_END: 802 case OPTION_GROUP: 803 case OPTION_BIT: 804 case OPTION_BOOLEAN: 805 case OPTION_INCR: 806 case OPTION_SET_UINT: 807 case OPTION_SET_PTR: 808 break; 809 } 810 811 if (pos <= USAGE_OPTS_WIDTH) 812 pad = USAGE_OPTS_WIDTH - pos; 813 else { 814 fputc('\n', stderr); 815 pad = USAGE_OPTS_WIDTH; 816 } 817 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 818 if (opts->flags & PARSE_OPT_NOBUILD) 819 fprintf(stderr, "%*s(not built-in because %s)\n", 820 USAGE_OPTS_WIDTH + USAGE_GAP, "", 821 opts->build_opt); 822 } 823 824 static int option__cmp(const void *va, const void *vb) 825 { 826 const struct option *a = va, *b = vb; 827 int sa = tolower(a->short_name), sb = tolower(b->short_name), ret; 828 829 if (sa == 0) 830 sa = 'z' + 1; 831 if (sb == 0) 832 sb = 'z' + 1; 833 834 ret = sa - sb; 835 836 if (ret == 0) { 837 const char *la = a->long_name ?: "", 838 *lb = b->long_name ?: ""; 839 ret = strcmp(la, lb); 840 } 841 842 return ret; 843 } 844 845 static struct option *options__order(const struct option *opts) 846 { 847 int nr_opts = 0, nr_group = 0, nr_parent = 0, len; 848 const struct option *o = NULL, *p = opts; 849 struct option *opt, *ordered = NULL, *group; 850 851 /* flatten the options that have parents */ 852 for (p = opts; p != NULL; p = o->parent) { 853 for (o = p; o->type != OPTION_END; o++) 854 ++nr_opts; 855 856 /* 857 * the length is given by the number of options plus a null 858 * terminator for the last loop iteration. 859 */ 860 len = sizeof(*o) * (nr_opts + !o->parent); 861 group = realloc(ordered, len); 862 if (!group) 863 goto out; 864 ordered = group; 865 memcpy(&ordered[nr_parent], p, sizeof(*o) * (nr_opts - nr_parent)); 866 867 nr_parent = nr_opts; 868 } 869 /* copy the last OPTION_END */ 870 memcpy(&ordered[nr_opts], o, sizeof(*o)); 871 872 /* sort each option group individually */ 873 for (opt = group = ordered; opt->type != OPTION_END; opt++) { 874 if (opt->type == OPTION_GROUP) { 875 qsort(group, nr_group, sizeof(*opt), option__cmp); 876 group = opt + 1; 877 nr_group = 0; 878 continue; 879 } 880 nr_group++; 881 } 882 qsort(group, nr_group, sizeof(*opt), option__cmp); 883 884 out: 885 return ordered; 886 } 887 888 static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx) 889 { 890 int i; 891 892 for (i = 1; i < ctx->argc; ++i) { 893 const char *arg = ctx->argv[i]; 894 895 if (arg[0] != '-') { 896 if (arg[1] == '\0') { 897 if (arg[0] == opt->short_name) 898 return true; 899 continue; 900 } 901 902 if (opt->long_name && strcmp(opt->long_name, arg) == 0) 903 return true; 904 905 if (opt->help && strcasestr(opt->help, arg) != NULL) 906 return true; 907 908 continue; 909 } 910 911 if (arg[1] == opt->short_name || 912 (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) 913 return true; 914 } 915 916 return false; 917 } 918 919 static int usage_with_options_internal(const char * const *usagestr, 920 const struct option *opts, int full, 921 struct parse_opt_ctx_t *ctx) 922 { 923 struct option *ordered; 924 925 if (!usagestr) 926 return PARSE_OPT_HELP; 927 928 setup_pager(); 929 930 if (error_buf) { 931 fprintf(stderr, " Error: %s\n", error_buf); 932 zfree(&error_buf); 933 } 934 935 fprintf(stderr, "\n Usage: %s\n", *usagestr++); 936 while (*usagestr && **usagestr) 937 fprintf(stderr, " or: %s\n", *usagestr++); 938 while (*usagestr) { 939 fprintf(stderr, "%s%s\n", 940 **usagestr ? " " : "", 941 *usagestr); 942 usagestr++; 943 } 944 945 if (opts->type != OPTION_GROUP) 946 fputc('\n', stderr); 947 948 ordered = options__order(opts); 949 if (ordered) 950 opts = ordered; 951 952 for ( ; opts->type != OPTION_END; opts++) { 953 if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx)) 954 continue; 955 print_option_help(opts, full); 956 } 957 958 fputc('\n', stderr); 959 960 free(ordered); 961 962 return PARSE_OPT_HELP; 963 } 964 965 void usage_with_options(const char * const *usagestr, 966 const struct option *opts) 967 { 968 usage_with_options_internal(usagestr, opts, 0, NULL); 969 exit(129); 970 } 971 972 void usage_with_options_msg(const char * const *usagestr, 973 const struct option *opts, const char *fmt, ...) 974 { 975 va_list ap; 976 char *tmp = error_buf; 977 978 va_start(ap, fmt); 979 if (vasprintf(&error_buf, fmt, ap) == -1) 980 die("vasprintf failed"); 981 va_end(ap); 982 983 free(tmp); 984 985 usage_with_options_internal(usagestr, opts, 0, NULL); 986 exit(129); 987 } 988 989 int parse_options_usage(const char * const *usagestr, 990 const struct option *opts, 991 const char *optstr, bool short_opt) 992 { 993 if (!usagestr) 994 goto opt; 995 996 fprintf(stderr, "\n Usage: %s\n", *usagestr++); 997 while (*usagestr && **usagestr) 998 fprintf(stderr, " or: %s\n", *usagestr++); 999 while (*usagestr) { 1000 fprintf(stderr, "%s%s\n", 1001 **usagestr ? " " : "", 1002 *usagestr); 1003 usagestr++; 1004 } 1005 fputc('\n', stderr); 1006 1007 opt: 1008 for ( ; opts->type != OPTION_END; opts++) { 1009 if (short_opt) { 1010 if (opts->short_name == *optstr) { 1011 print_option_help(opts, 0); 1012 break; 1013 } 1014 continue; 1015 } 1016 1017 if (opts->long_name == NULL) 1018 continue; 1019 1020 if (strstarts(opts->long_name, optstr)) 1021 print_option_help(opts, 0); 1022 if (strstarts("no-", optstr) && 1023 strstarts(opts->long_name, optstr + 3) && 1024 !(opts->flags & PARSE_OPT_NOAUTONEG)) 1025 print_option_help(opts, 0); 1026 } 1027 1028 return PARSE_OPT_HELP; 1029 } 1030 1031 1032 int parse_opt_verbosity_cb(const struct option *opt, 1033 const char *arg __maybe_unused, 1034 int unset) 1035 { 1036 int *target = opt->value; 1037 1038 if (unset) 1039 /* --no-quiet, --no-verbose */ 1040 *target = 0; 1041 else if (opt->short_name == 'v') { 1042 if (*target >= 0) 1043 (*target)++; 1044 else 1045 *target = 1; 1046 } else { 1047 if (*target <= 0) 1048 (*target)--; 1049 else 1050 *target = -1; 1051 } 1052 return 0; 1053 } 1054 1055 static struct option * 1056 find_option(struct option *opts, int shortopt, const char *longopt) 1057 { 1058 for (; opts->type != OPTION_END; opts++) { 1059 if ((shortopt && opts->short_name == shortopt) || 1060 (opts->long_name && longopt && 1061 !strcmp(opts->long_name, longopt))) 1062 return opts; 1063 } 1064 return NULL; 1065 } 1066 1067 void set_option_flag(struct option *opts, int shortopt, const char *longopt, 1068 int flag) 1069 { 1070 struct option *opt = find_option(opts, shortopt, longopt); 1071 1072 if (opt) 1073 opt->flags |= flag; 1074 return; 1075 } 1076 1077 void set_option_nobuild(struct option *opts, int shortopt, 1078 const char *longopt, 1079 const char *build_opt, 1080 bool can_skip) 1081 { 1082 struct option *opt = find_option(opts, shortopt, longopt); 1083 1084 if (!opt) 1085 return; 1086 1087 opt->flags |= PARSE_OPT_NOBUILD; 1088 opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0; 1089 opt->build_opt = build_opt; 1090 } 1091