aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 01:42:59 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 01:42:59 +0000
commit0bb4a23506c07c2b696a91661d38b86860e2e7be (patch)
tree2a69e566333a2b3f8c2988d7cce66d38f7a68ace
parent609f2ab4345e173ea944db774131e3615b3176a8 (diff)
downloadbusybox-w32-0bb4a23506c07c2b696a91661d38b86860e2e7be.tar.gz
busybox-w32-0bb4a23506c07c2b696a91661d38b86860e2e7be.tar.bz2
busybox-w32-0bb4a23506c07c2b696a91661d38b86860e2e7be.zip
hush: fix all testsuite failures on NOMMU except memory leak.
known TODOs: we do not pass traps and positional args yet.
-rw-r--r--shell/hush.c125
1 files changed, 103 insertions, 22 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 0313cfd78..13e962383 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1055,13 +1055,18 @@ static const char *get_local_var_value(const char *src)
1055 1055
1056/* str holds "NAME=VAL" and is expected to be malloced. 1056/* str holds "NAME=VAL" and is expected to be malloced.
1057 * We take ownership of it. 1057 * We take ownership of it.
1058 * flg_export is used by: 1058 * flg_export:
1059 * 0: do not export 1059 * 0: do not export
1060 * 1: export 1060 * 1: export
1061 * -1: if NAME is set, leave export status alone 1061 * -1: if NAME is set, leave export status alone
1062 * if NAME is not set, do not export 1062 * if NAME is not set, do not export
1063 * flg_read_only is set only when we handle -R var=val
1063 */ 1064 */
1064static int set_local_var(char *str, int flg_export) 1065#if BB_MMU
1066#define set_local_var(str, flg_export, flg_read_only) \
1067 set_local_var(str, flg_export)
1068#endif
1069static int set_local_var(char *str, int flg_export, int flg_read_only)
1065{ 1070{
1066 struct variable *cur; 1071 struct variable *cur;
1067 char *value; 1072 char *value;
@@ -1088,7 +1093,10 @@ static int set_local_var(char *str, int flg_export)
1088 /* We found an existing var with this name */ 1093 /* We found an existing var with this name */
1089 *value = '\0'; 1094 *value = '\0';
1090 if (cur->flg_read_only) { 1095 if (cur->flg_read_only) {
1091 bb_error_msg("%s: readonly variable", str); 1096#if !BB_MMU
1097 if (!flg_read_only)
1098#endif
1099 bb_error_msg("%s: readonly variable", str);
1092 free(str); 1100 free(str);
1093 return -1; 1101 return -1;
1094 } 1102 }
@@ -1119,6 +1127,7 @@ static int set_local_var(char *str, int flg_export)
1119 1127
1120 set_str_and_exp: 1128 set_str_and_exp:
1121 cur->varstr = str; 1129 cur->varstr = str;
1130 cur->flg_read_only = flg_read_only;
1122 exp: 1131 exp:
1123 if (flg_export == 1) 1132 if (flg_export == 1)
1124 cur->flg_export = 1; 1133 cur->flg_export = 1;
@@ -1182,7 +1191,7 @@ static void arith_set_local_var(const char *name, const char *val, int flags)
1182{ 1191{
1183 /* arith code doesnt malloc space, so do it for it */ 1192 /* arith code doesnt malloc space, so do it for it */
1184 char *var = xasprintf("%s=%s", name, val); 1193 char *var = xasprintf("%s=%s", name, val);
1185 set_local_var(var, flags); 1194 set_local_var(var, flags, 0);
1186} 1195}
1187#endif 1196#endif
1188 1197
@@ -1948,7 +1957,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
1948 } else { 1957 } else {
1949 char *new_var = xmalloc(strlen(var) + strlen(val) + 2); 1958 char *new_var = xmalloc(strlen(var) + strlen(val) + 2);
1950 sprintf(new_var, "%s=%s", var, val); 1959 sprintf(new_var, "%s=%s", var, val);
1951 set_local_var(new_var, -1); 1960 set_local_var(new_var, -1, 0);
1952 } 1961 }
1953 } 1962 }
1954 } 1963 }
@@ -2332,9 +2341,40 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
2332static void re_execute_shell(const char *s) NORETURN; 2341static void re_execute_shell(const char *s) NORETURN;
2333static void re_execute_shell(const char *s) 2342static void re_execute_shell(const char *s)
2334{ 2343{
2335//TODO: pass non-exported variables, traps, and functions 2344 struct variable *cur;
2336 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'", getpid(), s); 2345 char **argv, **pp;
2337 execl(bb_busybox_exec_path, "hush", "-c", s, NULL); 2346 unsigned cnt;
2347
2348 /* hush -$<pid> -?<exitcode> ... -c <cmd> NULL */
2349 cnt = 6;
2350 for (cur = G.top_var; cur; cur = cur->next) {
2351 if (!cur->flg_export || cur->flg_read_only)
2352 cnt += 2;
2353 }
2354//TODO: need to free these strings in parent!
2355 argv = pp = xmalloc(sizeof(argv[0]) * cnt);
2356 *pp++ = (char *) applet_name;
2357 *pp++ = xasprintf("-$%u", G.root_pid);
2358 *pp++ = xasprintf("-?%u", G.last_return_code);
2359 for (cur = G.top_var; cur; cur = cur->next) {
2360 if (cur->varstr == hush_version_str)
2361 continue;
2362 if (cur->flg_read_only) {
2363 *pp++ = (char *) "-R";
2364 *pp++ = cur->varstr;
2365 } else if (!cur->flg_export) {
2366 *pp++ = (char *) "-V";
2367 *pp++ = cur->varstr;
2368 }
2369 }
2370 *pp++ = (char *) "-c";
2371 *pp++ = (char *) s;
2372//TODO: pass $N
2373 *pp = NULL;
2374//TODO: pass traps and functions
2375
2376 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
2377 execv(bb_busybox_exec_path, argv);
2338//TODO: fallback for init=/bin/hush? 2378//TODO: fallback for init=/bin/hush?
2339 _exit(127); 2379 _exit(127);
2340} 2380}
@@ -2720,7 +2760,7 @@ static int run_pipe(struct pipe *pi)
2720 p = expand_string_to_string(*argv); 2760 p = expand_string_to_string(*argv);
2721 debug_printf_exec("set shell var:'%s'->'%s'\n", 2761 debug_printf_exec("set shell var:'%s'->'%s'\n",
2722 *argv, p); 2762 *argv, p);
2723 set_local_var(p, 0); 2763 set_local_var(p, 0, 0);
2724 argv++; 2764 argv++;
2725 } 2765 }
2726 /* Do we need to flag set_local_var() errors? 2766 /* Do we need to flag set_local_var() errors?
@@ -4094,7 +4134,7 @@ static int handle_dollar(struct parse_context *ctx,
4094 if (isalpha(ch)) { 4134 if (isalpha(ch)) {
4095 ch = i_getch(input); 4135 ch = i_getch(input);
4096#if !BB_MMU 4136#if !BB_MMU
4097 o_addchr(&ctx->as_string, ch); 4137 if (ctx) o_addchr(&ctx->as_string, ch);
4098#endif 4138#endif
4099 make_var: 4139 make_var:
4100 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4140 o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4107,7 +4147,7 @@ static int handle_dollar(struct parse_context *ctx,
4107 break; 4147 break;
4108 ch = i_getch(input); 4148 ch = i_getch(input);
4109#if !BB_MMU 4149#if !BB_MMU
4110 o_addchr(&ctx->as_string, ch); 4150 if (ctx) o_addchr(&ctx->as_string, ch);
4111#endif 4151#endif
4112 } 4152 }
4113 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4153 o_addchr(dest, SPECIAL_VAR_SYMBOL);
@@ -4115,7 +4155,7 @@ static int handle_dollar(struct parse_context *ctx,
4115 make_one_char_var: 4155 make_one_char_var:
4116 ch = i_getch(input); 4156 ch = i_getch(input);
4117#if !BB_MMU 4157#if !BB_MMU
4118 o_addchr(&ctx->as_string, ch); 4158 if (ctx) o_addchr(&ctx->as_string, ch);
4119#endif 4159#endif
4120 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4160 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4121 debug_printf_parse(": '%c'\n", ch); 4161 debug_printf_parse(": '%c'\n", ch);
@@ -4135,7 +4175,7 @@ static int handle_dollar(struct parse_context *ctx,
4135 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4175 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4136 ch = i_getch(input); 4176 ch = i_getch(input);
4137#if !BB_MMU 4177#if !BB_MMU
4138 o_addchr(&ctx->as_string, ch); 4178 if (ctx) o_addchr(&ctx->as_string, ch);
4139#endif 4179#endif
4140 /* XXX maybe someone will try to escape the '}' */ 4180 /* XXX maybe someone will try to escape the '}' */
4141 expansion = 0; 4181 expansion = 0;
@@ -4144,7 +4184,7 @@ static int handle_dollar(struct parse_context *ctx,
4144 while (1) { 4184 while (1) {
4145 ch = i_getch(input); 4185 ch = i_getch(input);
4146#if !BB_MMU 4186#if !BB_MMU
4147 o_addchr(&ctx->as_string, ch); 4187 if (ctx) o_addchr(&ctx->as_string, ch);
4148#endif 4188#endif
4149 if (ch == '}') 4189 if (ch == '}')
4150 break; 4190 break;
@@ -4211,19 +4251,32 @@ static int handle_dollar(struct parse_context *ctx,
4211 break; 4251 break;
4212 } 4252 }
4213 case '(': { 4253 case '(': {
4254#if !BB_MMU
4255 int pos;
4256#endif
4214 ch = i_getch(input); 4257 ch = i_getch(input);
4215#if !BB_MMU 4258#if !BB_MMU
4216 o_addchr(&ctx->as_string, ch); 4259 if (ctx) o_addchr(&ctx->as_string, ch);
4217#endif 4260#endif
4218#if ENABLE_SH_MATH_SUPPORT 4261#if ENABLE_SH_MATH_SUPPORT
4219 if (i_peek(input) == '(') { 4262 if (i_peek(input) == '(') {
4220 ch = i_getch(input); 4263 ch = i_getch(input);
4221#if !BB_MMU 4264#if !BB_MMU
4222 o_addchr(&ctx->as_string, ch); 4265 if (ctx) o_addchr(&ctx->as_string, ch);
4223#endif 4266#endif
4224 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4267 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4225 o_addchr(dest, /*quote_mask |*/ '+'); 4268 o_addchr(dest, /*quote_mask |*/ '+');
4269#if !BB_MMU
4270 pos = dest->length;
4271#endif
4226 add_till_closing_paren(dest, input, true); 4272 add_till_closing_paren(dest, input, true);
4273#if !BB_MMU
4274 if (ctx) {
4275 o_addstr(&ctx->as_string, dest->data + pos);
4276 o_addchr(&ctx->as_string, ')');
4277 o_addchr(&ctx->as_string, ')');
4278 }
4279#endif
4227 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4280 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4228 break; 4281 break;
4229 } 4282 }
@@ -4232,7 +4285,16 @@ static int handle_dollar(struct parse_context *ctx,
4232 //int pos = dest->length; 4285 //int pos = dest->length;
4233 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4286 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4234 o_addchr(dest, quote_mask | '`'); 4287 o_addchr(dest, quote_mask | '`');
4288#if !BB_MMU
4289 pos = dest->length;
4290#endif
4235 add_till_closing_paren(dest, input, false); 4291 add_till_closing_paren(dest, input, false);
4292#if !BB_MMU
4293 if (ctx) {
4294 o_addstr(&ctx->as_string, dest->data + pos);
4295 o_addchr(&ctx->as_string, '`');
4296 }
4297#endif
4236 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); 4298 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
4237 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4299 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4238#endif 4300#endif
@@ -4241,7 +4303,7 @@ static int handle_dollar(struct parse_context *ctx,
4241 case '_': 4303 case '_':
4242 ch = i_getch(input); 4304 ch = i_getch(input);
4243#if !BB_MMU 4305#if !BB_MMU
4244 o_addchr(&ctx->as_string, ch); 4306 if (ctx) o_addchr(&ctx->as_string, ch);
4245#endif 4307#endif
4246 ch = i_peek(input); 4308 ch = i_peek(input);
4247 if (isalnum(ch)) { /* it's $_name or $_123 */ 4309 if (isalnum(ch)) { /* it's $_name or $_123 */
@@ -4293,8 +4355,8 @@ static int parse_stream_dquoted(struct parse_context *ctx,
4293 if (ch != '\n') { 4355 if (ch != '\n') {
4294 next = i_peek(input); 4356 next = i_peek(input);
4295 } 4357 }
4296 debug_printf_parse(": ch=%c (%d) m=%d escape=%d\n", 4358 debug_printf_parse(": ch=%c (%d) escape=%d\n",
4297 ch, ch, m, dest->o_escape); 4359 ch, ch, dest->o_escape);
4298 if (ch == '\\') { 4360 if (ch == '\\') {
4299 if (next == EOF) { 4361 if (next == EOF) {
4300 syntax("\\<eof>"); 4362 syntax("\\<eof>");
@@ -4944,7 +5006,14 @@ int hush_main(int argc, char **argv)
4944 input = stdin; 5006 input = stdin;
4945 5007
4946 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ 5008 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
4947 while ((opt = getopt(argc, argv, "c:xins")) > 0) { 5009 while (1) {
5010 opt = getopt(argc, argv, "c:xins"
5011#if !BB_MMU
5012 "$:?:R:V:"
5013#endif
5014 );
5015 if (opt <= 0)
5016 break;
4948 switch (opt) { 5017 switch (opt) {
4949 case 'c': 5018 case 'c':
4950 G.global_argv = argv + optind; 5019 G.global_argv = argv + optind;
@@ -4965,6 +5034,18 @@ int hush_main(int argc, char **argv)
4965 /* "-s" means "read from stdin", but this is how we always 5034 /* "-s" means "read from stdin", but this is how we always
4966 * operate, so simply do nothing here. */ 5035 * operate, so simply do nothing here. */
4967 break; 5036 break;
5037#if !BB_MMU
5038 case '$':
5039 G.root_pid = xatoi_u(optarg);
5040 break;
5041 case '?':
5042 G.last_return_code = xatoi_u(optarg);
5043 break;
5044 case 'R':
5045 case 'V':
5046 set_local_var(xstrdup(optarg), 0, opt == 'R');
5047 break;
5048#endif
4968 case 'n': 5049 case 'n':
4969 case 'x': 5050 case 'x':
4970 if (!set_mode('-', opt)) 5051 if (!set_mode('-', opt))
@@ -5293,7 +5374,7 @@ static int builtin_export(char **argv)
5293 return EXIT_SUCCESS; 5374 return EXIT_SUCCESS;
5294 } 5375 }
5295 5376
5296 set_local_var(xstrdup(name), 1); 5377 set_local_var(xstrdup(name), 1, 0);
5297 return EXIT_SUCCESS; 5378 return EXIT_SUCCESS;
5298} 5379}
5299 5380
@@ -5406,7 +5487,7 @@ static int builtin_read(char **argv)
5406 const char *name = argv[1] ? argv[1] : "REPLY"; 5487 const char *name = argv[1] ? argv[1] : "REPLY";
5407 5488
5408 string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL); 5489 string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL);
5409 return set_local_var(string, 0); 5490 return set_local_var(string, 0, 0);
5410} 5491}
5411 5492
5412/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set 5493/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set