aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-11 17:21:14 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-11 17:21:14 +0200
commit419db0391e47444dd12fb052613fd415694d04f0 (patch)
tree0b989526666cd6150b7bae6151f9273c4a5db487 /shell
parent129e1ce72c28ec14aee459cceffc25ed9d5cae85 (diff)
downloadbusybox-w32-419db0391e47444dd12fb052613fd415694d04f0.tar.gz
busybox-w32-419db0391e47444dd12fb052613fd415694d04f0.tar.bz2
busybox-w32-419db0391e47444dd12fb052613fd415694d04f0.zip
hush: implement "silent" optstrings of ":opts"
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash_test/ash-getopts/getopt_silent.right6
-rwxr-xr-xshell/ash_test/ash-getopts/getopt_silent.tests23
-rw-r--r--shell/hush.c48
-rw-r--r--shell/hush_test/hush-getopts/getopt_silent.right6
-rwxr-xr-xshell/hush_test/hush-getopts/getopt_silent.tests23
5 files changed, 89 insertions, 17 deletions
diff --git a/shell/ash_test/ash-getopts/getopt_silent.right b/shell/ash_test/ash-getopts/getopt_silent.right
new file mode 100644
index 000000000..03d4eb149
--- /dev/null
+++ b/shell/ash_test/ash-getopts/getopt_silent.right
@@ -0,0 +1,6 @@
1*** optstring:':ac' args:-a -b -c
21 rc:0 var:'a' OPTIND:2 OPTARG:''
32 rc:0 var:'?' OPTIND:3 OPTARG:'b'
43 rc:0 var:'c' OPTIND:4 OPTARG:''
54 rc:1 var:'?' OPTIND:4 OPTARG:''
65 rc:1 var:'?' OPTIND:4 OPTARG:''
diff --git a/shell/ash_test/ash-getopts/getopt_silent.tests b/shell/ash_test/ash-getopts/getopt_silent.tests
new file mode 100755
index 000000000..097d7ba85
--- /dev/null
+++ b/shell/ash_test/ash-getopts/getopt_silent.tests
@@ -0,0 +1,23 @@
1# Open Group Base Specifications Issue 7:
2# """
3# If an unknown option is met, VAR shall be set to "?". In this case,
4# if the first character in optstring is ":", OPTARG shall be set
5# to the option character found, but no output shall be written
6# to standard error; otherwise, the shell variable OPTARG shall be
7# unset and a diagnostic message shall be written to standard error."
8# ...
9# If an option-argument is missing:
10# If the first character of optstring is ":", VAR shall be set to ":"
11# and OPTARG shall be set to the option character found.
12# """
13
14echo "*** optstring:':ac' args:-a -b -c"
15getopts ":ac" var -a -b -c; echo "1 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
16getopts ":ac" var -a -b -c; echo "2 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
17getopts ":ac" var -a -b -c; echo "3 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
18getopts ":ac" var -a -b -c; echo "4 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
19# Previous line should result in "rc:1", which is normally treated
20# in getopts loops as exit condition.
21# Nevertheless, let's verify that calling it yet another time doesn't do
22# anything weird:
23getopts ":ac" var -a -b -c; echo "5 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
diff --git a/shell/hush.c b/shell/hush.c
index 1e58d71e0..517b8c109 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9877,11 +9877,6 @@ static int FAST_FUNC builtin_getopts(char **argv)
9877/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html 9877/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
9878 9878
9879TODO: 9879TODO:
9880If an invalid option is seen, getopts places ? into VAR and, if
9881not silent, prints an error message and unsets OPTARG. If
9882getopts is silent, the option character found is placed in
9883OPTARG and no diagnostic message is printed.
9884
9885If a required argument is not found, and getopts is not silent, 9880If a required argument is not found, and getopts is not silent,
9886a question mark (?) is placed in VAR, OPTARG is unset, and a 9881a question mark (?) is placed in VAR, OPTARG is unset, and a
9887diagnostic message is printed. If getopts is silent, then a 9882diagnostic message is printed. If getopts is silent, then a
@@ -9902,11 +9897,16 @@ Test that VAR is a valid variable name?
9902 return EXIT_FAILURE; 9897 return EXIT_FAILURE;
9903 } 9898 }
9904 9899
9905 cp = get_local_var_value("OPTERR"); 9900 if (optstring[0] == ':') {
9906 opterr = cp ? atoi(cp) : 1; 9901 opterr = 0;
9902 } else {
9903 cp = get_local_var_value("OPTERR");
9904 opterr = cp ? atoi(cp) : 1;
9905 }
9907 cp = get_local_var_value("OPTIND"); 9906 cp = get_local_var_value("OPTIND");
9908 optind = cp ? atoi(cp) : 0; 9907 optind = cp ? atoi(cp) : 0;
9909 optarg = NULL; 9908 optarg = NULL;
9909 cbuf[1] = '\0';
9910 9910
9911 /* getopts stops on first non-option. Add "+" to force that */ 9911 /* getopts stops on first non-option. Add "+" to force that */
9912 /*if (optstring[0] != '+')*/ { 9912 /*if (optstring[0] != '+')*/ {
@@ -9920,25 +9920,39 @@ Test that VAR is a valid variable name?
9920 else 9920 else
9921 argv = G.global_argv; 9921 argv = G.global_argv;
9922 c = getopt(string_array_len(argv), argv, optstring); 9922 c = getopt(string_array_len(argv), argv, optstring);
9923
9924 /* Set OPTARG */
9925 /* Always set or unset, never left as-is, even on exit/error:
9926 * "If no option was found, or if the option that was found
9927 * does not have an option-argument, OPTARG shall be unset."
9928 */
9929 cp = optarg;
9930 if (c == '?') {
9931 /* If ":optstring" and unknown option is seen,
9932 * it is stored to OPTARG.
9933 */
9934 if (optstring[1] == ':') {
9935 cbuf[0] = optopt;
9936 cp = cbuf;
9937 }
9938 }
9939 if (cp)
9940 set_local_var_from_halves("OPTARG", cp);
9941 else
9942 unset_local_var("OPTARG");
9943
9944 /* Convert -1 to "?" */
9923 exitcode = EXIT_SUCCESS; 9945 exitcode = EXIT_SUCCESS;
9924 if (c < 0) { /* -1: end of options */ 9946 if (c < 0) { /* -1: end of options */
9925 exitcode = EXIT_FAILURE; 9947 exitcode = EXIT_FAILURE;
9926 c = '?'; 9948 c = '?';
9927 } 9949 }
9950
9951 /* Set OPTIND */
9928 cbuf[0] = c; 9952 cbuf[0] = c;
9929 cbuf[1] = '\0';
9930 set_local_var_from_halves(var, cbuf); 9953 set_local_var_from_halves(var, cbuf);
9931 set_local_var_from_halves("OPTIND", utoa(optind)); 9954 set_local_var_from_halves("OPTIND", utoa(optind));
9932 9955
9933 /* Always set or unset, never left as-is, even on exit/error:
9934 * "If no option was found, or if the option that was found
9935 * does not have an option-argument, OPTARG shall be unset."
9936 */
9937 if (optarg)
9938 set_local_var_from_halves("OPTARG", optarg);
9939 else
9940 unset_local_var("OPTARG");
9941
9942 return exitcode; 9956 return exitcode;
9943} 9957}
9944#endif 9958#endif
diff --git a/shell/hush_test/hush-getopts/getopt_silent.right b/shell/hush_test/hush-getopts/getopt_silent.right
new file mode 100644
index 000000000..03d4eb149
--- /dev/null
+++ b/shell/hush_test/hush-getopts/getopt_silent.right
@@ -0,0 +1,6 @@
1*** optstring:':ac' args:-a -b -c
21 rc:0 var:'a' OPTIND:2 OPTARG:''
32 rc:0 var:'?' OPTIND:3 OPTARG:'b'
43 rc:0 var:'c' OPTIND:4 OPTARG:''
54 rc:1 var:'?' OPTIND:4 OPTARG:''
65 rc:1 var:'?' OPTIND:4 OPTARG:''
diff --git a/shell/hush_test/hush-getopts/getopt_silent.tests b/shell/hush_test/hush-getopts/getopt_silent.tests
new file mode 100755
index 000000000..097d7ba85
--- /dev/null
+++ b/shell/hush_test/hush-getopts/getopt_silent.tests
@@ -0,0 +1,23 @@
1# Open Group Base Specifications Issue 7:
2# """
3# If an unknown option is met, VAR shall be set to "?". In this case,
4# if the first character in optstring is ":", OPTARG shall be set
5# to the option character found, but no output shall be written
6# to standard error; otherwise, the shell variable OPTARG shall be
7# unset and a diagnostic message shall be written to standard error."
8# ...
9# If an option-argument is missing:
10# If the first character of optstring is ":", VAR shall be set to ":"
11# and OPTARG shall be set to the option character found.
12# """
13
14echo "*** optstring:':ac' args:-a -b -c"
15getopts ":ac" var -a -b -c; echo "1 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
16getopts ":ac" var -a -b -c; echo "2 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
17getopts ":ac" var -a -b -c; echo "3 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
18getopts ":ac" var -a -b -c; echo "4 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"
19# Previous line should result in "rc:1", which is normally treated
20# in getopts loops as exit condition.
21# Nevertheless, let's verify that calling it yet another time doesn't do
22# anything weird:
23getopts ":ac" var -a -b -c; echo "5 rc:$? var:'$var' OPTIND:$OPTIND OPTARG:'$OPTARG'"