diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-20 10:13:08 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-20 10:13:08 +0000 |
commit | 11fb7cf5afab2ab7bb77e6a22a3ff0564953b179 (patch) | |
tree | 1d9a05b707448a7a10949e663a0f0e0c43d51856 | |
parent | 1bb3d7e45021f9ca55d8ad6ba9193fda0e129284 (diff) | |
download | busybox-w32-11fb7cf5afab2ab7bb77e6a22a3ff0564953b179.tar.gz busybox-w32-11fb7cf5afab2ab7bb77e6a22a3ff0564953b179.tar.bz2 busybox-w32-11fb7cf5afab2ab7bb77e6a22a3ff0564953b179.zip |
hush: fix set [--] params. Closes bug 199.
function old new delta
builtin_set 55 194 +139
add_strings_to_strings - 130 +130
add_string_to_strings 110 26 -84
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 269/-84) Total: 185 bytes
-rw-r--r-- | shell/hush.c | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/shell/hush.c b/shell/hush.c index 3b87855b6..e6189f841 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -471,8 +471,9 @@ struct globals { | |||
471 | smallint fake_mode; | 471 | smallint fake_mode; |
472 | /* these three support $?, $#, and $1 */ | 472 | /* these three support $?, $#, and $1 */ |
473 | smalluint last_return_code; | 473 | smalluint last_return_code; |
474 | smalluint global_args_malloced; | ||
475 | int global_argc; /* NB: $# + 1 */ | ||
474 | char **global_argv; | 476 | char **global_argv; |
475 | int global_argc; | ||
476 | #if ENABLE_HUSH_LOOPS | 477 | #if ENABLE_HUSH_LOOPS |
477 | unsigned depth_break_continue; | 478 | unsigned depth_break_continue; |
478 | unsigned depth_of_loop; | 479 | unsigned depth_of_loop; |
@@ -646,7 +647,7 @@ static char *unbackslash(char *src) | |||
646 | return dst; | 647 | return dst; |
647 | } | 648 | } |
648 | 649 | ||
649 | static char **add_strings_to_strings(char **strings, char **add) | 650 | static char **add_strings_to_strings(char **strings, char **add, int need_to_dup) |
650 | { | 651 | { |
651 | int i; | 652 | int i; |
652 | unsigned count1; | 653 | unsigned count1; |
@@ -671,7 +672,7 @@ static char **add_strings_to_strings(char **strings, char **add) | |||
671 | v[count1 + count2] = NULL; | 672 | v[count1 + count2] = NULL; |
672 | i = count2; | 673 | i = count2; |
673 | while (--i >= 0) | 674 | while (--i >= 0) |
674 | v[count1 + i] = add[i]; | 675 | v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]); |
675 | return v; | 676 | return v; |
676 | } | 677 | } |
677 | 678 | ||
@@ -680,7 +681,7 @@ static char **add_string_to_strings(char **strings, char *add) | |||
680 | char *v[2]; | 681 | char *v[2]; |
681 | v[0] = add; | 682 | v[0] = add; |
682 | v[1] = NULL; | 683 | v[1] = NULL; |
683 | return add_strings_to_strings(strings, v); | 684 | return add_strings_to_strings(strings, v, /*dup:*/ 0); |
684 | } | 685 | } |
685 | 686 | ||
686 | static void putenv_all(char **strings) | 687 | static void putenv_all(char **strings) |
@@ -4644,17 +4645,68 @@ static int builtin_read(char **argv) | |||
4644 | return set_local_var(string, 0); | 4645 | return set_local_var(string, 0); |
4645 | } | 4646 | } |
4646 | 4647 | ||
4647 | /* built-in 'set [VAR=value]' handler */ | 4648 | /* built-in 'set' handler |
4649 | * SUSv3 says: | ||
4650 | * set [-abCefmnuvx] [-h] [-o option] [argument...] | ||
4651 | * set [+abCefmnuvx] [+h] [+o option] [argument...] | ||
4652 | * set -- [argument...] | ||
4653 | * set -o | ||
4654 | * set +o | ||
4655 | * Implementations shall support the options in both their hyphen and | ||
4656 | * plus-sign forms. These options can also be specified as options to sh. | ||
4657 | * Examples: | ||
4658 | * Write out all variables and their values: set | ||
4659 | * Set $1, $2, and $3 and set "$#" to 3: set c a b | ||
4660 | * Turn on the -x and -v options: set -xv | ||
4661 | * Unset all positional parameters: set -- | ||
4662 | * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x" | ||
4663 | * Set the positional parameters to the expansion of x, even if x expands | ||
4664 | * with a leading '-' or '+': set -- $x | ||
4665 | * | ||
4666 | * So far, we only support "set -- [argument...]" by ignoring all options | ||
4667 | * (also, "-o option" will be mishandled by taking "option" as parameter #1). | ||
4668 | */ | ||
4648 | static int builtin_set(char **argv) | 4669 | static int builtin_set(char **argv) |
4649 | { | 4670 | { |
4650 | char *temp = argv[1]; | ||
4651 | struct variable *e; | 4671 | struct variable *e; |
4672 | char **pp; | ||
4673 | char *arg = *++argv; | ||
4652 | 4674 | ||
4653 | if (temp == NULL) | 4675 | if (arg == NULL) { |
4654 | for (e = G.top_var; e; e = e->next) | 4676 | for (e = G.top_var; e; e = e->next) |
4655 | puts(e->varstr); | 4677 | puts(e->varstr); |
4656 | else | 4678 | } else { |
4657 | set_local_var(xstrdup(temp), 0); | 4679 | /* NB: G.global_argv[0] ($0) is never freed/changed */ |
4680 | |||
4681 | if (G.global_args_malloced) { | ||
4682 | pp = G.global_argv; | ||
4683 | while (*++pp) | ||
4684 | free(*pp); | ||
4685 | G.global_argv[1] = NULL; | ||
4686 | } else { | ||
4687 | G.global_args_malloced = 1; | ||
4688 | pp = xzalloc(sizeof(pp[0]) * 2); | ||
4689 | pp[0] = G.global_argv[0]; /* retain $0 */ | ||
4690 | G.global_argv = pp; | ||
4691 | } | ||
4692 | do { | ||
4693 | if (arg[0] == '+') | ||
4694 | continue; | ||
4695 | if (arg[0] != '-') | ||
4696 | break; | ||
4697 | if (arg[1] == '-' && arg[2] == '\0') { | ||
4698 | argv++; | ||
4699 | break; | ||
4700 | } | ||
4701 | } while ((arg = *++argv) != NULL); | ||
4702 | /* Now argv[0] is 1st argument */ | ||
4703 | |||
4704 | /* This realloc's G.global_argv */ | ||
4705 | G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1); | ||
4706 | G.global_argc = 1; | ||
4707 | while (*++pp) | ||
4708 | G.global_argc++; | ||
4709 | } | ||
4658 | 4710 | ||
4659 | return EXIT_SUCCESS; | 4711 | return EXIT_SUCCESS; |
4660 | } | 4712 | } |