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