9
0
Fork 0

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:
Sascha Hauer 2012-02-25 17:10:57 +01:00
parent 2034ee47b1
commit aed0e6ba03
4 changed files with 50 additions and 13 deletions

View File

@ -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)

View File

@ -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");

View File

@ -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 */

View File

@ -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)
{ {