aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-20 10:13:08 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-20 10:13:08 +0000
commit11fb7cf5afab2ab7bb77e6a22a3ff0564953b179 (patch)
tree1d9a05b707448a7a10949e663a0f0e0c43d51856
parent1bb3d7e45021f9ca55d8ad6ba9193fda0e129284 (diff)
downloadbusybox-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.c70
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
649static char **add_strings_to_strings(char **strings, char **add) 650static 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
686static void putenv_all(char **strings) 687static 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 */
4648static int builtin_set(char **argv) 4669static 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}