summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorMike Frysinger2009-03-28 13:44:51 +0000
committerMike Frysinger2009-03-28 13:44:51 +0000
commitad88d5a4cfe200191bce4db41b447969719cb8ac (patch)
tree30c97089e248db47d2d8ad95d23efe07a44b3add /shell/hush.c
parent19a7ea126a6f05232ee7d4b786bafab8e28a8beb (diff)
downloadbusybox-ad88d5a4cfe200191bce4db41b447969719cb8ac.zip
busybox-ad88d5a4cfe200191bce4db41b447969719cb8ac.tar.gz
unify `set` handling with command line processing, fixup `set` argv processing so it doesnt clobber argv when setting options, and barf on unhandled set options
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 2dd59bb..3565cbc 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -516,6 +516,7 @@ static int builtin_read(char **argv);
static int builtin_test(char **argv);
static int builtin_true(char **argv);
static int builtin_set(char **argv);
+static int builtin_set_mode(const char, const char);
static int builtin_shift(char **argv);
static int builtin_source(char **argv);
static int builtin_umask(char **argv);
@@ -4256,13 +4257,14 @@ int hush_main(int argc, char **argv)
* we have to have some stuff (ctty, etc) */
/* G.interactive_fd++; */
break;
- case 'n':
- G.fake_mode = 1;
- break;
case 's':
/* "-s" means "read from stdin", but this is how we always
* operate, so simply do nothing here. */
break;
+ case 'n':
+ case 'x':
+ if (!builtin_set_mode('-', opt))
+ break;
default:
#ifndef BB_VER
fprintf(stderr, "Usage: sh [FILE]...\n"
@@ -4613,10 +4615,11 @@ static int builtin_read(char **argv)
return set_local_var(string, 0);
}
-/* built-in 'set' handler
+/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
+ * built-in 'set' handler
* SUSv3 says:
- * set [-abCefmnuvx] [-h] [-o option] [argument...]
- * set [+abCefmnuvx] [+h] [+o option] [argument...]
+ * set [-abCefhmnuvx] [-o option] [argument...]
+ * set [+abCefhmnuvx] [+o option] [argument...]
* set -- [argument...]
* set -o
* set +o
@@ -4631,9 +4634,18 @@ static int builtin_read(char **argv)
* Set the positional parameters to the expansion of x, even if x expands
* with a leading '-' or '+': set -- $x
*
- * So far, we only support "set -- [argument...]" by ignoring all options
- * (also, "-o option" will be mishandled by taking "option" as parameter #1).
+ * So far, we only support "set -- [argument...]" and some of the short names.
*/
+static int builtin_set_mode(const char cstate, const char mode)
+{
+ int state = (cstate == '-' ? 1 : 0);
+ switch (mode) {
+ case 'n': G.fake_mode = state; break;
+ case 'x': /*G.debug_mode = state;*/ break;
+ default: return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
static int builtin_set(char **argv)
{
int n;
@@ -4647,18 +4659,28 @@ static int builtin_set(char **argv)
return EXIT_SUCCESS;
}
- do {
- if (arg[0] == '+')
+ do {
+ if (!strcmp(arg, "--")) {
+ ++argv;
+ goto set_argv;
+ }
+
+ if (arg[0] == '+' || arg[0] == '-') {
+ for (n = 1; arg[n]; ++n)
+ if (builtin_set_mode(arg[0], arg[n]))
+ goto error;
continue;
- if (arg[0] != '-')
- break;
- if (arg[1] == '-' && arg[2] == '\0') {
- argv++;
- break;
}
+
+ break;
} while ((arg = *++argv) != NULL);
/* Now argv[0] is 1st argument */
+ /* Only reset global_argv if we didn't process anything */
+ if (arg == NULL)
+ return EXIT_SUCCESS;
+ set_argv:
+
/* NB: G.global_argv[0] ($0) is never freed/changed */
g_argv = G.global_argv;
if (G.global_args_malloced) {
@@ -4681,6 +4703,11 @@ static int builtin_set(char **argv)
G.global_argc = n;
return EXIT_SUCCESS;
+
+ /* Nothing known, so abort */
+ error:
+ bb_error_msg("set: %s: invalid option", arg);
+ return EXIT_FAILURE;
}
static int builtin_shift(char **argv)