[PATCH 2/2] getopt: save and restore context

Sascha Hauer s.hauer at pengutronix.de
Mon Feb 27 03:38:46 EST 2012


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 at pengutronix.de>
---
 common/command.c |   12 ++++++++----
 common/hush.c    |   15 ++++++++++-----
 include/getopt.h |   14 ++++++++++++--
 lib/getopt.c     |   22 ++++++++++++++++++++--
 4 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/common/command.c b/common/command.c
index ab02ed5..de2c3a9 100644
--- a/common/command.c
+++ b/common/command.c
@@ -91,8 +91,9 @@ int execute_command(int argc, char **argv)
 {
 	struct command *cmdtp;
 	int ret;
+	struct getopt_context gc;
 
-	getopt_reset();
+	getopt_context_store(&gc);
 
 	/* Look up command in command table */
 	if ((cmdtp = find_cmd(argv[0]))) {
@@ -100,17 +101,20 @@ int execute_command(int argc, char **argv)
 		ret = cmdtp->cmd(cmdtp, argc, argv);
 		if (ret == COMMAND_ERROR_USAGE) {
 			barebox_cmd_usage(cmdtp);
-			return COMMAND_ERROR;
+			ret = COMMAND_ERROR;
 		}
-		return ret;
 	} else {
 #ifdef CONFIG_CMD_HELP
 		printf ("Unknown command '%s' - try 'help'\n", argv[0]);
 #else
 		printf ("Unknown command '%s'\n", argv[0]);
 #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)
diff --git a/common/hush.c b/common/hush.c
index b59e59d..97dc13c 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -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)
 {
 	char *optstring, *var;
-	int opt;
+	int opt, ret = 0;
 	char opta[2];
 	struct option *o;
+	struct getopt_context gc;
 
 	if (child->argc != 3)
 		return -2 - 1;
@@ -512,7 +513,7 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
 	optstring = child->argv[1];
 	var = child->argv[2];
 
-	getopt_reset();
+	getopt_context_store(&gc);
 
 	if (!ctx->options_parsed) {
 		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;
 
-	if (list_empty(&ctx->options))
-		return -1;
+	if (list_empty(&ctx->options)) {
+		ret = -1;
+		goto out;
+	}
 
 	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);
 	list_del(&o->list);
 	free(o);
+out:
+	getopt_context_restore(&gc);
 
-	return 0;
+	return ret;
 }
 
 BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
diff --git a/include/getopt.h b/include/getopt.h
index 4f43ac4..ed55e22 100644
--- a/include/getopt.h
+++ b/include/getopt.h
@@ -40,10 +40,20 @@ extern char *optarg;
 
 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
- * 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 */
diff --git a/lib/getopt.c b/lib/getopt.c
index 5c35ee1..043ba05 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -34,12 +34,30 @@ EXPORT_SYMBOL(optarg);
 static int optindex = 1; /* option index in the current argv[] element */
 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;
 	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)
 {
-- 
1.7.9.1




More information about the barebox mailing list