getopt: save and restore context
execute_command is the single point where commands are executed and thus a new getopt context is needed. currently we call getopt_reset here to reset the context. This breaks though when a command tries to run a command itself by calling execute_command or run_command. In this case we have to store the context and restore it afterwards. The same is necessary in builtin_getopt. Currently noone does this so this one shouldn't fix a bug, but merely allows us to do such things later. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
2034ee47b1
commit
aed0e6ba03
|
@ -91,8 +91,9 @@ int execute_command(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct command *cmdtp;
|
struct command *cmdtp;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct getopt_context gc;
|
||||||
|
|
||||||
getopt_reset();
|
getopt_context_store(&gc);
|
||||||
|
|
||||||
/* Look up command in command table */
|
/* Look up command in command table */
|
||||||
if ((cmdtp = find_cmd(argv[0]))) {
|
if ((cmdtp = find_cmd(argv[0]))) {
|
||||||
|
@ -100,17 +101,20 @@ int execute_command(int argc, char **argv)
|
||||||
ret = cmdtp->cmd(cmdtp, argc, argv);
|
ret = cmdtp->cmd(cmdtp, argc, argv);
|
||||||
if (ret == COMMAND_ERROR_USAGE) {
|
if (ret == COMMAND_ERROR_USAGE) {
|
||||||
barebox_cmd_usage(cmdtp);
|
barebox_cmd_usage(cmdtp);
|
||||||
return COMMAND_ERROR;
|
ret = COMMAND_ERROR;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_CMD_HELP
|
#ifdef CONFIG_CMD_HELP
|
||||||
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
|
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
|
||||||
#else
|
#else
|
||||||
printf ("Unknown command '%s'\n", argv[0]);
|
printf ("Unknown command '%s'\n", argv[0]);
|
||||||
#endif
|
#endif
|
||||||
return -1; /* give up after bad command */
|
ret = -1; /* give up after bad command */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getopt_context_restore(&gc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int register_command(struct command *cmd)
|
int register_command(struct command *cmd)
|
||||||
|
|
|
@ -502,9 +502,10 @@ static void setup_string_in_str(struct in_str *i, const char *s)
|
||||||
static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
|
static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
|
||||||
{
|
{
|
||||||
char *optstring, *var;
|
char *optstring, *var;
|
||||||
int opt;
|
int opt, ret = 0;
|
||||||
char opta[2];
|
char opta[2];
|
||||||
struct option *o;
|
struct option *o;
|
||||||
|
struct getopt_context gc;
|
||||||
|
|
||||||
if (child->argc != 3)
|
if (child->argc != 3)
|
||||||
return -2 - 1;
|
return -2 - 1;
|
||||||
|
@ -512,7 +513,7 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
|
||||||
optstring = child->argv[1];
|
optstring = child->argv[1];
|
||||||
var = child->argv[2];
|
var = child->argv[2];
|
||||||
|
|
||||||
getopt_reset();
|
getopt_context_store(&gc);
|
||||||
|
|
||||||
if (!ctx->options_parsed) {
|
if (!ctx->options_parsed) {
|
||||||
while((opt = getopt(ctx->global_argc, ctx->global_argv, optstring)) > 0) {
|
while((opt = getopt(ctx->global_argc, ctx->global_argv, optstring)) > 0) {
|
||||||
|
@ -525,8 +526,10 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
|
||||||
|
|
||||||
ctx->options_parsed = 1;
|
ctx->options_parsed = 1;
|
||||||
|
|
||||||
if (list_empty(&ctx->options))
|
if (list_empty(&ctx->options)) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
o = list_first_entry(&ctx->options, struct option, list);
|
o = list_first_entry(&ctx->options, struct option, list);
|
||||||
|
|
||||||
|
@ -538,8 +541,10 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
|
||||||
free(o->optarg);
|
free(o->optarg);
|
||||||
list_del(&o->list);
|
list_del(&o->list);
|
||||||
free(o);
|
free(o);
|
||||||
|
out:
|
||||||
|
getopt_context_restore(&gc);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
|
BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
|
||||||
|
|
|
@ -40,10 +40,20 @@ extern char *optarg;
|
||||||
|
|
||||||
int getopt(int argc, char *argv[], char *optstring);
|
int getopt(int argc, char *argv[], char *optstring);
|
||||||
|
|
||||||
|
struct getopt_context {
|
||||||
|
int opterr;
|
||||||
|
int optind;
|
||||||
|
int optopt;
|
||||||
|
int nonopts;
|
||||||
|
int optindex;
|
||||||
|
char *optarg;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do not start a new process for each getopt() run, so we
|
* We do not start a new process for each getopt() run, so we
|
||||||
* need this function to reset the static variables.
|
* need this function to save and restore the context.
|
||||||
*/
|
*/
|
||||||
void getopt_reset(void);
|
void getopt_context_store(struct getopt_context *ctx);
|
||||||
|
void getopt_context_restore(struct getopt_context *ctx);
|
||||||
|
|
||||||
#endif /* __GETOPT_H */
|
#endif /* __GETOPT_H */
|
||||||
|
|
22
lib/getopt.c
22
lib/getopt.c
|
@ -34,12 +34,30 @@ EXPORT_SYMBOL(optarg);
|
||||||
static int optindex = 1; /* option index in the current argv[] element */
|
static int optindex = 1; /* option index in the current argv[] element */
|
||||||
static int nonopts = 0; /* number of nonopts found */
|
static int nonopts = 0; /* number of nonopts found */
|
||||||
|
|
||||||
void getopt_reset(void)
|
void getopt_context_store(struct getopt_context *gc)
|
||||||
{
|
{
|
||||||
|
gc->optind = optind;
|
||||||
|
gc->opterr = opterr;
|
||||||
|
gc->optopt = optopt;
|
||||||
|
gc->optarg = optarg;
|
||||||
|
gc->nonopts = nonopts;
|
||||||
|
gc->optindex = optindex;
|
||||||
|
|
||||||
optind = opterr = optindex = 1;
|
optind = opterr = optindex = 1;
|
||||||
nonopts = 0;
|
nonopts = 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(getopt_reset);
|
EXPORT_SYMBOL(getopt_context_store);
|
||||||
|
|
||||||
|
void getopt_context_restore(struct getopt_context *gc)
|
||||||
|
{
|
||||||
|
optind = gc->optind;
|
||||||
|
opterr = gc->opterr;
|
||||||
|
optopt = gc->optopt;
|
||||||
|
optarg = gc->optarg;
|
||||||
|
nonopts = gc->nonopts;
|
||||||
|
optindex = gc->optindex;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(getopt_context_restore);
|
||||||
|
|
||||||
int getopt(int argc, char *argv[], char *optstring)
|
int getopt(int argc, char *argv[], char *optstring)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue