int sandbox_early_getopt_check(void) { struct sandbox_state *state = state_get_current(); struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start; size_t num_options = __u_boot_sandbox_option_count(); size_t i; int max_arg_len, max_noarg_len; /* parse_err will be a string of the faulting option */ if (!state->parse_err) return 0; if (strcmp(state->parse_err, "help")) { printf("u-boot: error: failed while parsing option: %s\n" "\ttry running with --help for more information.\n", state->parse_err); os_exit(1); } printf( "u-boot, a command line test interface to U-Boot\n\n" "Usage: u-boot [options]\n" "Options:\n"); max_arg_len = 0; for (i = 0; i < num_options; ++i) max_arg_len = max((int)strlen(sb_opt[i]->flag), max_arg_len); max_noarg_len = max_arg_len + 7; for (i = 0; i < num_options; ++i) { struct sandbox_cmdline_option *opt = sb_opt[i]; /* first output the short flag if it has one */ if (opt->flag_short >= 0x100) printf(" "); else printf(" -%c, ", opt->flag_short); /* then the long flag */ if (opt->has_arg) printf("--%-*s <arg> ", max_arg_len, opt->flag); else printf("--%-*s", max_noarg_len, opt->flag); /* finally the help text */ printf(" %s\n", opt->help); } os_exit(0); }
int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) { struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start; size_t num_options = __u_boot_sandbox_option_count(); size_t i; int hidden_short_opt; size_t si; int c; if (short_opts || long_opts) return 1; state->argc = argc; state->argv = argv; /* dynamically construct the arguments to the system getopt_long */ short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1); long_opts = os_malloc(sizeof(*long_opts) * num_options); if (!short_opts || !long_opts) return 1; /* * getopt_long requires "val" to be unique (since that is what the * func returns), so generate unique values automatically for flags * that don't have a short option. pick 0x100 as that is above the * single byte range (where ASCII/ISO-XXXX-X charsets live). */ hidden_short_opt = 0x100; si = 0; for (i = 0; i < num_options; ++i) { long_opts[i].name = sb_opt[i]->flag; long_opts[i].has_arg = sb_opt[i]->has_arg ? required_argument : no_argument; long_opts[i].flag = NULL; if (sb_opt[i]->flag_short) { short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short; if (long_opts[i].has_arg == required_argument) short_opts[si++] = ':'; } else long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++; } short_opts[si] = '\0'; /* we need to handle output ourselves since u-boot provides printf */ opterr = 0; /* * walk all of the options the user gave us on the command line, * figure out what u-boot option structure they belong to (via * the unique short val key), and call the appropriate callback. */ while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { for (i = 0; i < num_options; ++i) { if (sb_opt[i]->flag_short == c) { if (sb_opt[i]->callback(state, optarg)) { state->parse_err = sb_opt[i]->flag; return 0; } break; } } if (i == num_options) { /* * store the faulting flag for later display. we have to * store the flag itself as the getopt parsing itself is * tricky: need to handle the following flags (assume all * of the below are unknown): * -a optopt='a' optind=<next> * -abbbb optopt='a' optind=<this> * -aaaaa optopt='a' optind=<this> * --a optopt=0 optind=<this> * as you can see, it is impossible to determine the exact * faulting flag without doing the parsing ourselves, so * we just report the specific flag that failed. */ if (optopt) { static char parse_err[3] = { '-', 0, '\0', }; parse_err[1] = optopt; state->parse_err = parse_err; } else state->parse_err = argv[optind - 1]; break; } } return 0; }