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