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
This commit is contained in:
parent
19a7ea126a
commit
ad88d5a4cf
59
shell/hush.c
59
shell/hush.c
@ -516,6 +516,7 @@ static int builtin_read(char **argv);
|
|||||||
static int builtin_test(char **argv);
|
static int builtin_test(char **argv);
|
||||||
static int builtin_true(char **argv);
|
static int builtin_true(char **argv);
|
||||||
static int builtin_set(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_shift(char **argv);
|
||||||
static int builtin_source(char **argv);
|
static int builtin_source(char **argv);
|
||||||
static int builtin_umask(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) */
|
* we have to have some stuff (ctty, etc) */
|
||||||
/* G.interactive_fd++; */
|
/* G.interactive_fd++; */
|
||||||
break;
|
break;
|
||||||
case 'n':
|
|
||||||
G.fake_mode = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
case 's':
|
||||||
/* "-s" means "read from stdin", but this is how we always
|
/* "-s" means "read from stdin", but this is how we always
|
||||||
* operate, so simply do nothing here. */
|
* operate, so simply do nothing here. */
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
case 'x':
|
||||||
|
if (!builtin_set_mode('-', opt))
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
#ifndef BB_VER
|
#ifndef BB_VER
|
||||||
fprintf(stderr, "Usage: sh [FILE]...\n"
|
fprintf(stderr, "Usage: sh [FILE]...\n"
|
||||||
@ -4613,10 +4615,11 @@ static int builtin_read(char **argv)
|
|||||||
return set_local_var(string, 0);
|
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:
|
* SUSv3 says:
|
||||||
* set [-abCefmnuvx] [-h] [-o option] [argument...]
|
* set [-abCefhmnuvx] [-o option] [argument...]
|
||||||
* set [+abCefmnuvx] [+h] [+o option] [argument...]
|
* set [+abCefhmnuvx] [+o option] [argument...]
|
||||||
* set -- [argument...]
|
* set -- [argument...]
|
||||||
* set -o
|
* set -o
|
||||||
* 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
|
* Set the positional parameters to the expansion of x, even if x expands
|
||||||
* with a leading '-' or '+': set -- $x
|
* with a leading '-' or '+': set -- $x
|
||||||
*
|
*
|
||||||
* So far, we only support "set -- [argument...]" by ignoring all options
|
* So far, we only support "set -- [argument...]" and some of the short names.
|
||||||
* (also, "-o option" will be mishandled by taking "option" as parameter #1).
|
|
||||||
*/
|
*/
|
||||||
|
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)
|
static int builtin_set(char **argv)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
@ -4647,18 +4659,28 @@ static int builtin_set(char **argv)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (arg[0] == '+')
|
if (!strcmp(arg, "--")) {
|
||||||
continue;
|
++argv;
|
||||||
if (arg[0] != '-')
|
goto set_argv;
|
||||||
break;
|
|
||||||
if (arg[1] == '-' && arg[2] == '\0') {
|
|
||||||
argv++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg[0] == '+' || arg[0] == '-') {
|
||||||
|
for (n = 1; arg[n]; ++n)
|
||||||
|
if (builtin_set_mode(arg[0], arg[n]))
|
||||||
|
goto error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
} while ((arg = *++argv) != NULL);
|
} while ((arg = *++argv) != NULL);
|
||||||
/* Now argv[0] is 1st argument */
|
/* 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 */
|
/* NB: G.global_argv[0] ($0) is never freed/changed */
|
||||||
g_argv = G.global_argv;
|
g_argv = G.global_argv;
|
||||||
if (G.global_args_malloced) {
|
if (G.global_args_malloced) {
|
||||||
@ -4681,6 +4703,11 @@ static int builtin_set(char **argv)
|
|||||||
G.global_argc = n;
|
G.global_argc = n;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
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)
|
static int builtin_shift(char **argv)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user