[git commit] hush: teach getopts to set/unset OPTARG

Denys Vlasenko vda.linux at googlemail.com
Fri Aug 11 00:05:21 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=81f962f3df0d7194b7a52c6f83259727759094c4
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash_test/ash-getopts/getopt_optarg.right       | 18 ++++++++++++++++++
 shell/ash_test/ash-getopts/getopt_optarg.tests       | 16 ++++++++++++++++
 shell/hush.c                                         | 10 +++++-----
 shell/hush_test/hush-getopts/getopt_optarg.right     | 18 ++++++++++++++++++
 shell/hush_test/hush-getopts/getopt_optarg.tests     | 16 ++++++++++++++++
 shell/hush_test/hush-getopts/getopt_positional.tests |  1 -
 6 files changed, 73 insertions(+), 6 deletions(-)

diff --git a/shell/ash_test/ash-getopts/getopt_optarg.right b/shell/ash_test/ash-getopts/getopt_optarg.right
new file mode 100644
index 0000000..dff28de
--- /dev/null
+++ b/shell/ash_test/ash-getopts/getopt_optarg.right
@@ -0,0 +1,18 @@
+*** no OPTIND, optstring:'w:et' args:-q -w e -r -t -y
+Illegal option -q
+var:'?' OPTIND:2 OPTARG:''
+var:'w' OPTIND:4 OPTARG:'e'
+Illegal option -r
+var:'?' OPTIND:5 OPTARG:''
+var:'t' OPTIND:6 OPTARG:''
+Illegal option -y
+var:'?' OPTIND:7 OPTARG:''
+exited: var:'?' OPTIND:7 OPTARG:''
+*** OPTIND=0, optstring:'w:et' args:-w 1 -w2 -w -e -e -t -t
+var:'w' OPTIND:3 OPTARG:'1'
+var:'w' OPTIND:4 OPTARG:'2'
+var:'w' OPTIND:6 OPTARG:'-e'
+var:'e' OPTIND:7 OPTARG:''
+var:'t' OPTIND:8 OPTARG:''
+var:'t' OPTIND:9 OPTARG:''
+exited: var:'?' OPTIND:9 OPTARG:''
diff --git a/shell/ash_test/ash-getopts/getopt_optarg.tests b/shell/ash_test/ash-getopts/getopt_optarg.tests
new file mode 100755
index 0000000..b346284
--- /dev/null
+++ b/shell/ash_test/ash-getopts/getopt_optarg.tests
@@ -0,0 +1,16 @@
+set -- -q -w e -r -t -y
+echo "*** no OPTIND, optstring:'w:et' args:$*"
+var=QWERTY
+OPTARG=ASDFGH
+while getopts "w:et" var; do
+	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+done
+echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+
+set -- -w 1 -w2 -w -e -e -t -t
+echo "*** OPTIND=0, optstring:'w:et' args:$*"
+OPTIND=0
+while getopts "w:et" var; do
+	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+done
+echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
diff --git a/shell/hush.c b/shell/hush.c
index dba12c1..f9a8de4 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9874,11 +9874,6 @@ static int FAST_FUNC builtin_getopts(char **argv)
 {
 /*
 TODO:
-if a character is followed by a colon, the option is expected to have
-an argument, which should be separated from it by white space.
-When an option requires an argument, getopts places that argument into
-the variable OPTARG.
-
 If an invalid option is seen, getopts places ? into VAR and, if
 not silent, prints an error message and unsets OPTARG. If
 getopts is silent, the option character found is placed in
@@ -9906,6 +9901,7 @@ Test that VAR is a valid variable name?
 	opterr = cp ? atoi(cp) : 1;
 	cp = get_local_var_value("OPTIND");
 	optind = cp ? atoi(cp) : 0;
+	optarg = NULL;
 
 	/* getopts stops on first non-option. Add "+" to force that */
 	/*if (optstring[0] != '+')*/ {
@@ -9924,6 +9920,10 @@ Test that VAR is a valid variable name?
 		exitcode = EXIT_FAILURE;
 		c = '?';
 	}
+	if (optarg)
+		set_local_var_from_halves("OPTARG", optarg);
+	else
+		unset_local_var("OPTARG");
 	cbuf[0] = c;
 	cbuf[1] = '\0';
 	set_local_var_from_halves(var, cbuf);
diff --git a/shell/hush_test/hush-getopts/getopt_optarg.right b/shell/hush_test/hush-getopts/getopt_optarg.right
new file mode 100644
index 0000000..9dbd846
--- /dev/null
+++ b/shell/hush_test/hush-getopts/getopt_optarg.right
@@ -0,0 +1,18 @@
+*** no OPTIND, optstring:'w:et' args:-q -w e -r -t -y
+./getopt_optarg.tests: invalid option -- q
+var:'?' OPTIND:2 OPTARG:''
+var:'w' OPTIND:4 OPTARG:'e'
+./getopt_optarg.tests: invalid option -- r
+var:'?' OPTIND:5 OPTARG:''
+var:'t' OPTIND:6 OPTARG:''
+./getopt_optarg.tests: invalid option -- y
+var:'?' OPTIND:7 OPTARG:''
+exited: var:'?' OPTIND:7 OPTARG:''
+*** OPTIND=0, optstring:'w:et' args:-w 1 -w2 -w -e -e -t -t
+var:'w' OPTIND:3 OPTARG:'1'
+var:'w' OPTIND:4 OPTARG:'2'
+var:'w' OPTIND:6 OPTARG:'-e'
+var:'e' OPTIND:7 OPTARG:''
+var:'t' OPTIND:8 OPTARG:''
+var:'t' OPTIND:9 OPTARG:''
+exited: var:'?' OPTIND:9 OPTARG:''
diff --git a/shell/hush_test/hush-getopts/getopt_optarg.tests b/shell/hush_test/hush-getopts/getopt_optarg.tests
new file mode 100755
index 0000000..b346284
--- /dev/null
+++ b/shell/hush_test/hush-getopts/getopt_optarg.tests
@@ -0,0 +1,16 @@
+set -- -q -w e -r -t -y
+echo "*** no OPTIND, optstring:'w:et' args:$*"
+var=QWERTY
+OPTARG=ASDFGH
+while getopts "w:et" var; do
+	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+done
+echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+
+set -- -w 1 -w2 -w -e -e -t -t
+echo "*** OPTIND=0, optstring:'w:et' args:$*"
+OPTIND=0
+while getopts "w:et" var; do
+	echo "var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
+done
+echo "exited: var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
diff --git a/shell/hush_test/hush-getopts/getopt_positional.tests b/shell/hush_test/hush-getopts/getopt_positional.tests
index a5404a2..ddf0633 100755
--- a/shell/hush_test/hush-getopts/getopt_positional.tests
+++ b/shell/hush_test/hush-getopts/getopt_positional.tests
@@ -4,5 +4,4 @@ var=QWERTY
 while getopts "we" var; do
 	echo "var:'$var' OPTIND:$OPTIND"
 done
-# unfortunately, "rc:0" is shown since while's overall exitcode is "success"
 echo "exited: var:'$var' OPTIND:$OPTIND"


More information about the busybox-cvs mailing list