aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/shell/hush.c b/shell/hush.c
index cdaa67a3b..8e632e0af 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -91,7 +91,7 @@
91 * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*" 91 * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*"
92 */ 92 */
93//config:config HUSH 93//config:config HUSH
94//config: bool "hush (68 kb)" 94//config: bool "hush (70 kb)"
95//config: default y 95//config: default y
96//config: select SHELL_HUSH 96//config: select SHELL_HUSH
97//config: help 97//config: help
@@ -2255,14 +2255,14 @@ static const char *get_cwd(int force)
2255/* 2255/*
2256 * Shell and environment variable support 2256 * Shell and environment variable support
2257 */ 2257 */
2258static struct variable **get_ptr_to_local_var(const char *name, unsigned len) 2258static struct variable **get_ptr_to_local_var(const char *name)
2259{ 2259{
2260 struct variable **pp; 2260 struct variable **pp;
2261 struct variable *cur; 2261 struct variable *cur;
2262 2262
2263 pp = &G.top_var; 2263 pp = &G.top_var;
2264 while ((cur = *pp) != NULL) { 2264 while ((cur = *pp) != NULL) {
2265 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') 2265 if (varcmp(cur->varstr, name) == 0)
2266 return pp; 2266 return pp;
2267 pp = &cur->next; 2267 pp = &cur->next;
2268 } 2268 }
@@ -2272,21 +2272,20 @@ static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
2272static const char* FAST_FUNC get_local_var_value(const char *name) 2272static const char* FAST_FUNC get_local_var_value(const char *name)
2273{ 2273{
2274 struct variable **vpp; 2274 struct variable **vpp;
2275 unsigned len = strlen(name);
2276 2275
2277 if (G.expanded_assignments) { 2276 if (G.expanded_assignments) {
2278 char **cpp = G.expanded_assignments; 2277 char **cpp = G.expanded_assignments;
2279 while (*cpp) { 2278 while (*cpp) {
2280 char *cp = *cpp; 2279 char *cp = *cpp;
2281 if (strncmp(cp, name, len) == 0 && cp[len] == '=') 2280 if (varcmp(cp, name) == 0)
2282 return cp + len + 1; 2281 return strchr(cp, '=') + 1;
2283 cpp++; 2282 cpp++;
2284 } 2283 }
2285 } 2284 }
2286 2285
2287 vpp = get_ptr_to_local_var(name, len); 2286 vpp = get_ptr_to_local_var(name);
2288 if (vpp) 2287 if (vpp)
2289 return (*vpp)->varstr + len + 1; 2288 return strchr((*vpp)->varstr, '=') + 1;
2290 2289
2291 if (strcmp(name, "PPID") == 0) 2290 if (strcmp(name, "PPID") == 0)
2292 return utoa(G.root_ppid); 2291 return utoa(G.root_ppid);
@@ -2319,13 +2318,11 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
2319} 2318}
2320 2319
2321#if ENABLE_HUSH_GETOPTS 2320#if ENABLE_HUSH_GETOPTS
2322static void handle_changed_special_names(const char *name, unsigned name_len) 2321static void handle_changed_special_names(const char *name)
2323{ 2322{
2324 if (name_len == 6) { 2323 if (varcmp(name, "OPTIND") == 0) {
2325 if (strncmp(name, "OPTIND", 6) == 0) { 2324 G.getopt_count = 0;
2326 G.getopt_count = 0; 2325 return;
2327 return;
2328 }
2329 } 2326 }
2330} 2327}
2331#else 2328#else
@@ -2476,7 +2473,7 @@ static int set_local_var(char *str, unsigned flags)
2476 } 2473 }
2477 free(free_me); 2474 free(free_me);
2478 2475
2479 handle_changed_special_names(cur->varstr, name_len - 1); 2476 handle_changed_special_names(cur->varstr);
2480 2477
2481 return retval; 2478 return retval;
2482} 2479}
@@ -2499,16 +2496,14 @@ static void set_pwd_var(unsigned flag)
2499} 2496}
2500 2497
2501#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS 2498#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS
2502static int unset_local_var_len(const char *name, int name_len) 2499static int unset_local_var(const char *name)
2503{ 2500{
2504 struct variable *cur; 2501 struct variable *cur;
2505 struct variable **cur_pp; 2502 struct variable **cur_pp;
2506 2503
2507 cur_pp = &G.top_var; 2504 cur_pp = &G.top_var;
2508 while ((cur = *cur_pp) != NULL) { 2505 while ((cur = *cur_pp) != NULL) {
2509 if (strncmp(cur->varstr, name, name_len) == 0 2506 if (varcmp(cur->varstr, name) == 0) {
2510 && cur->varstr[name_len] == '='
2511 ) {
2512 if (cur->flg_read_only) { 2507 if (cur->flg_read_only) {
2513 bb_error_msg("%s: readonly variable", name); 2508 bb_error_msg("%s: readonly variable", name);
2514 return EXIT_FAILURE; 2509 return EXIT_FAILURE;
@@ -2527,15 +2522,10 @@ static int unset_local_var_len(const char *name, int name_len)
2527 } 2522 }
2528 2523
2529 /* Handle "unset LINENO" et al even if did not find the variable to unset */ 2524 /* Handle "unset LINENO" et al even if did not find the variable to unset */
2530 handle_changed_special_names(name, name_len); 2525 handle_changed_special_names(name);
2531 2526
2532 return EXIT_SUCCESS; 2527 return EXIT_SUCCESS;
2533} 2528}
2534
2535static int unset_local_var(const char *name)
2536{
2537 return unset_local_var_len(name, strlen(name));
2538}
2539#endif 2529#endif
2540 2530
2541 2531
@@ -2581,7 +2571,7 @@ static void set_vars_and_save_old(char **strings)
2581 eq = strchr(*s, '='); 2571 eq = strchr(*s, '=');
2582 if (HUSH_DEBUG && !eq) 2572 if (HUSH_DEBUG && !eq)
2583 bb_simple_error_msg_and_die("BUG in varexp4"); 2573 bb_simple_error_msg_and_die("BUG in varexp4");
2584 var_pp = get_ptr_to_local_var(*s, eq - *s); 2574 var_pp = get_ptr_to_local_var(*s);
2585 if (var_pp) { 2575 if (var_pp) {
2586 var_p = *var_pp; 2576 var_p = *var_pp;
2587 if (var_p->flg_read_only) { 2577 if (var_p->flg_read_only) {
@@ -4316,7 +4306,7 @@ static int done_word(struct parse_context *ctx)
4316 || endofname(command->argv[0])[0] != '\0' 4306 || endofname(command->argv[0])[0] != '\0'
4317 ) { 4307 ) {
4318 /* bash says just "not a valid identifier" */ 4308 /* bash says just "not a valid identifier" */
4319 syntax_error("bad variable name in for"); 4309 syntax_error("bad for loop variable");
4320 return 1; 4310 return 1;
4321 } 4311 }
4322 /* Force FOR to have just one word (variable name) */ 4312 /* Force FOR to have just one word (variable name) */
@@ -4693,6 +4683,11 @@ static int parse_group(struct parse_context *ctx,
4693 syntax_error_unexpected_ch(ch); 4683 syntax_error_unexpected_ch(ch);
4694 return -1; 4684 return -1;
4695 } 4685 }
4686//bash allows functions named "123", "..", "return"!
4687// if (endofname(command->argv[0])[0] != '\0') {
4688// syntax_error("bad function name");
4689// return -1;
4690// }
4696 nommu_addchr(&ctx->as_string, ch); 4691 nommu_addchr(&ctx->as_string, ch);
4697 command->cmd_type = CMD_FUNCDEF; 4692 command->cmd_type = CMD_FUNCDEF;
4698 goto skip; 4693 goto skip;
@@ -6398,7 +6393,7 @@ static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n,
6398 if (!dest.o_expflags) { 6393 if (!dest.o_expflags) {
6399 if (ch == EOF) 6394 if (ch == EOF)
6400 break; 6395 break;
6401 if (!dquoted && strchr(G.ifs, ch)) { 6396 if (!dquoted && !(output->o_expflags & EXP_FLAG_SINGLEWORD) && strchr(G.ifs, ch)) {
6402 /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word. 6397 /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word.
6403 * do not assume we are at the start of the word (PREFIX above). 6398 * do not assume we are at the start of the word (PREFIX above).
6404 */ 6399 */
@@ -11178,7 +11173,7 @@ static int FAST_FUNC builtin_umask(char **argv)
11178} 11173}
11179#endif 11174#endif
11180 11175
11181#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP 11176#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY || ENABLE_HUSH_SET || ENABLE_HUSH_TRAP
11182static void print_escaped(const char *s) 11177static void print_escaped(const char *s)
11183{ 11178{
11184//TODO? bash "set" does not quote variables which contain only alnums and "%+,-./:=@_~", 11179//TODO? bash "set" does not quote variables which contain only alnums and "%+,-./:=@_~",
@@ -11215,7 +11210,7 @@ static int helper_export_local(char **argv, unsigned flags)
11215 if (*name_end == '\0') { 11210 if (*name_end == '\0') {
11216 struct variable *var, **vpp; 11211 struct variable *var, **vpp;
11217 11212
11218 vpp = get_ptr_to_local_var(name, name_end - name); 11213 vpp = get_ptr_to_local_var(name);
11219 var = vpp ? *vpp : NULL; 11214 var = vpp ? *vpp : NULL;
11220 11215
11221 if (flags & SETFLAG_UNEXPORT) { 11216 if (flags & SETFLAG_UNEXPORT) {
@@ -11317,8 +11312,8 @@ static int FAST_FUNC builtin_export(char **argv)
11317 11312
11318 if (!p) /* wtf? take next variable */ 11313 if (!p) /* wtf? take next variable */
11319 continue; 11314 continue;
11320 /* export var= */ 11315 /* "export VAR=" */
11321 printf("export %.*s", (int)(p - s) + 1, s); 11316 printf("%s %.*s", "export", (int)(p - s) + 1, s);
11322 print_escaped(p + 1); 11317 print_escaped(p + 1);
11323 putchar('\n'); 11318 putchar('\n');
11324# endif 11319# endif
@@ -11362,8 +11357,15 @@ static int FAST_FUNC builtin_readonly(char **argv)
11362 struct variable *e; 11357 struct variable *e;
11363 for (e = G.top_var; e; e = e->next) { 11358 for (e = G.top_var; e; e = e->next) {
11364 if (e->flg_read_only) { 11359 if (e->flg_read_only) {
11365//TODO: quote value: readonly VAR='VAL' 11360 const char *s = e->varstr;
11366 printf("readonly %s\n", e->varstr); 11361 const char *p = strchr(s, '=');
11362
11363 if (!p) /* wtf? take next variable */
11364 continue;
11365 /* "readonly VAR=" */
11366 printf("%s %.*s", "readonly", (int)(p - s) + 1, s);
11367 print_escaped(p + 1);
11368 putchar('\n');
11367 } 11369 }
11368 } 11370 }
11369 return EXIT_SUCCESS; 11371 return EXIT_SUCCESS;