summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-15 00:11:22 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-15 00:11:22 +0000
commit8f0c89e05a7b52f8c5ae7b451de6fd50732aeb45 (patch)
tree9bf309fce9eff03da8980e84d3de5741627bf96d /shell/hush.c
parentbc7177187f6b4f32c2f9562358294dfc7b521f67 (diff)
downloadbusybox-w32-1_13_4.tar.gz
busybox-w32-1_13_4.tar.bz2
busybox-w32-1_13_4.zip
apply post-1.13.3 fixes, bump version to 1.13.41_13_4
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c95
1 files changed, 82 insertions, 13 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 421272971..9e7b10535 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -458,8 +458,11 @@ struct globals {
458 smallint fake_mode; 458 smallint fake_mode;
459 /* these three support $?, $#, and $1 */ 459 /* these three support $?, $#, and $1 */
460 smalluint last_return_code; 460 smalluint last_return_code;
461 char **global_argv; 461 /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */
462 smalluint global_args_malloced;
463 /* how many non-NULL argv's we have. NB: $# + 1 */
462 int global_argc; 464 int global_argc;
465 char **global_argv;
463#if ENABLE_HUSH_LOOPS 466#if ENABLE_HUSH_LOOPS
464 unsigned depth_break_continue; 467 unsigned depth_break_continue;
465 unsigned depth_of_loop; 468 unsigned depth_of_loop;
@@ -633,7 +636,7 @@ static char *unbackslash(char *src)
633 return dst; 636 return dst;
634} 637}
635 638
636static char **add_strings_to_strings(char **strings, char **add) 639static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
637{ 640{
638 int i; 641 int i;
639 unsigned count1; 642 unsigned count1;
@@ -658,7 +661,7 @@ static char **add_strings_to_strings(char **strings, char **add)
658 v[count1 + count2] = NULL; 661 v[count1 + count2] = NULL;
659 i = count2; 662 i = count2;
660 while (--i >= 0) 663 while (--i >= 0)
661 v[count1 + i] = add[i]; 664 v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
662 return v; 665 return v;
663} 666}
664 667
@@ -667,7 +670,7 @@ static char **add_string_to_strings(char **strings, char *add)
667 char *v[2]; 670 char *v[2];
668 v[0] = add; 671 v[0] = add;
669 v[1] = NULL; 672 v[1] = NULL;
670 return add_strings_to_strings(strings, v); 673 return add_strings_to_strings(strings, v, /*dup:*/ 0);
671} 674}
672 675
673static void putenv_all(char **strings) 676static void putenv_all(char **strings)
@@ -1213,8 +1216,13 @@ static int o_glob(o_string *o, int n)
1213 * Otherwise, just finish current list[] and start new */ 1216 * Otherwise, just finish current list[] and start new */
1214static int o_save_ptr(o_string *o, int n) 1217static int o_save_ptr(o_string *o, int n)
1215{ 1218{
1216 if (o->o_glob) 1219 if (o->o_glob) { /* if globbing is requested */
1217 return o_glob(o, n); /* o_save_ptr_helper is inside */ 1220 /* If o->has_empty_slot, list[n] was already globbed
1221 * (if it was requested back then when it was filled)
1222 * so don't do that again! */
1223 if (!o->has_empty_slot)
1224 return o_glob(o, n); /* o_save_ptr_helper is inside */
1225 }
1218 return o_save_ptr_helper(o, n); 1226 return o_save_ptr_helper(o, n);
1219} 1227}
1220 1228
@@ -4279,6 +4287,11 @@ int hush_main(int argc, char **argv)
4279 switch (opt) { 4287 switch (opt) {
4280 case 'c': 4288 case 'c':
4281 G.global_argv = argv + optind; 4289 G.global_argv = argv + optind;
4290 if (!argv[optind]) {
4291 /* -c 'script' (no params): prevent empty $0 */
4292 *--G.global_argv = argv[0];
4293 optind--;
4294 } /* else -c 'script' PAR0 PAR1: $0 is PAR0 */
4282 G.global_argc = argc - optind; 4295 G.global_argc = argc - optind;
4283 opt = parse_and_run_string(optarg, 0 /* parse_flag */); 4296 opt = parse_and_run_string(optarg, 0 /* parse_flag */);
4284 goto final_return; 4297 goto final_return;
@@ -4639,17 +4652,68 @@ static int builtin_read(char **argv)
4639 return set_local_var(string, 0); 4652 return set_local_var(string, 0);
4640} 4653}
4641 4654
4642/* built-in 'set [VAR=value]' handler */ 4655/* built-in 'set' handler
4656 * SUSv3 says:
4657 * set [-abCefmnuvx] [-h] [-o option] [argument...]
4658 * set [+abCefmnuvx] [+h] [+o option] [argument...]
4659 * set -- [argument...]
4660 * set -o
4661 * set +o
4662 * Implementations shall support the options in both their hyphen and
4663 * plus-sign forms. These options can also be specified as options to sh.
4664 * Examples:
4665 * Write out all variables and their values: set
4666 * Set $1, $2, and $3 and set "$#" to 3: set c a b
4667 * Turn on the -x and -v options: set -xv
4668 * Unset all positional parameters: set --
4669 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
4670 * Set the positional parameters to the expansion of x, even if x expands
4671 * with a leading '-' or '+': set -- $x
4672 *
4673 * So far, we only support "set -- [argument...]" by ignoring all options
4674 * (also, "-o option" will be mishandled by taking "option" as parameter #1).
4675 */
4643static int builtin_set(char **argv) 4676static int builtin_set(char **argv)
4644{ 4677{
4645 char *temp = argv[1];
4646 struct variable *e; 4678 struct variable *e;
4679 char **pp;
4680 char *arg = *++argv;
4647 4681
4648 if (temp == NULL) 4682 if (arg == NULL) {
4649 for (e = G.top_var; e; e = e->next) 4683 for (e = G.top_var; e; e = e->next)
4650 puts(e->varstr); 4684 puts(e->varstr);
4651 else 4685 } else {
4652 set_local_var(xstrdup(temp), 0); 4686 /* NB: G.global_argv[0] ($0) is never freed/changed */
4687
4688 if (G.global_args_malloced) {
4689 pp = G.global_argv;
4690 while (*++pp)
4691 free(*pp);
4692 G.global_argv[1] = NULL;
4693 } else {
4694 G.global_args_malloced = 1;
4695 pp = xzalloc(sizeof(pp[0]) * 2);
4696 pp[0] = G.global_argv[0]; /* retain $0 */
4697 G.global_argv = pp;
4698 }
4699 do {
4700 if (arg[0] == '+')
4701 continue;
4702 if (arg[0] != '-')
4703 break;
4704 if (arg[1] == '-' && arg[2] == '\0') {
4705 argv++;
4706 break;
4707 }
4708 } while ((arg = *++argv) != NULL);
4709 /* Now argv[0] is 1st argument */
4710
4711 /* This realloc's G.global_argv */
4712 G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1);
4713 G.global_argc = 1;
4714 while (*++pp)
4715 G.global_argc++;
4716 }
4653 4717
4654 return EXIT_SUCCESS; 4718 return EXIT_SUCCESS;
4655} 4719}
@@ -4661,9 +4725,14 @@ static int builtin_shift(char **argv)
4661 n = atoi(argv[1]); 4725 n = atoi(argv[1]);
4662 } 4726 }
4663 if (n >= 0 && n < G.global_argc) { 4727 if (n >= 0 && n < G.global_argc) {
4664 G.global_argv[n] = G.global_argv[0]; 4728 if (G.global_args_malloced) {
4729 int m = 1;
4730 while (m <= n)
4731 free(G.global_argv[m++]);
4732 }
4665 G.global_argc -= n; 4733 G.global_argc -= n;
4666 G.global_argv += n; 4734 memmove(&G.global_argv[1], &G.global_argv[n+1],
4735 G.global_argc * sizeof(G.global_argv[0]));
4667 return EXIT_SUCCESS; 4736 return EXIT_SUCCESS;
4668 } 4737 }
4669 return EXIT_FAILURE; 4738 return EXIT_FAILURE;