From ad88d5a4cfe200191bce4db41b447969719cb8ac Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Mar 2009 13:44:51 +0000 Subject: 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 --- shell/hush.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 2dd59bbb4..3565cbca3 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) -- cgit v1.2.3