summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-16 09:36:55 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-16 09:36:55 +0000
commit8f6bdb42df745425ba0ac085467105e9cc61c817 (patch)
tree06e545effca8a1a64a812f19f1cc63e16892e055 /shell/hush.c
parent418a7fb29b19e42818b5df681c83b3bfc62db3c6 (diff)
downloadbusybox-w32-8f6bdb42df745425ba0ac085467105e9cc61c817.tar.gz
busybox-w32-8f6bdb42df745425ba0ac085467105e9cc61c817.tar.bz2
busybox-w32-8f6bdb42df745425ba0ac085467105e9cc61c817.zip
hush: fix incorrect processing of echo "'$var'".
hush: rename map[] and MAP_xxx, making them easier to understand. hush: move testcase (which now passes) from hush-bugs to hush-parsing
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c50
1 files changed, 25 insertions, 25 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 87e003db4..e49c0c989 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -71,7 +71,7 @@
71 * memory leak finding and plugging - done? 71 * memory leak finding and plugging - done?
72 * more testing, especially quoting rules and redirection 72 * more testing, especially quoting rules and redirection
73 * document how quoting rules not precisely followed for variable assignments 73 * document how quoting rules not precisely followed for variable assignments
74 * maybe change map[] to use 2-bit entries 74 * maybe change charmap[] to use 2-bit entries
75 * (eventually) remove all the printf's 75 * (eventually) remove all the printf's
76 * 76 *
77 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 77 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
@@ -281,12 +281,12 @@ extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
281 281
282/* "globals" within this file */ 282/* "globals" within this file */
283enum { 283enum {
284 MAP_ORDINARY = 0, 284 CHAR_ORDINARY = 0,
285 MAP_FLOWTROUGH_IF_QUOTED = 1, 285 CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */
286 MAP_IFS_IF_UNQUOTED = 2, /* flow through if quoted too */ 286 CHAR_IFS = 2, /* treated as ordinary if quoted */
287 MAP_NEVER_FLOWTROUGH = 3, 287 CHAR_SPECIAL = 3, /* example: $ */
288}; 288};
289static unsigned char map[256]; 289static unsigned char charmap[256];
290static const char *ifs; 290static const char *ifs;
291static int fake_mode; 291static int fake_mode;
292static struct close_me *close_me_head; 292static struct close_me *close_me_head;
@@ -2311,7 +2311,7 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
2311 * Caller can deallocate entire list by single free(list). */ 2311 * Caller can deallocate entire list by single free(list). */
2312 2312
2313/* Helpers first: 2313/* Helpers first:
2314 * count_XXX estimates, how large block do we need. It's okay 2314 * count_XXX estimates size of the block we need. It's okay
2315 * to over-estimate sizes a bit, if it makes code simpler */ 2315 * to over-estimate sizes a bit, if it makes code simpler */
2316static int count_ifs(const char *str) 2316static int count_ifs(const char *str)
2317{ 2317{
@@ -3360,17 +3360,17 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3360 debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger); 3360 debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
3361 3361
3362 while ((ch = b_getch(input)) != EOF) { 3362 while ((ch = b_getch(input)) != EOF) {
3363 m = map[ch]; 3363 m = charmap[ch];
3364 next = (ch == '\n') ? '\0' : b_peek(input); 3364 next = (ch == '\n') ? '\0' : b_peek(input);
3365 debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n", 3365 debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
3366 ch, ch, m, dest->quote); 3366 ch, ch, m, dest->quote);
3367 if (m == MAP_ORDINARY 3367 if (m == CHAR_ORDINARY
3368 || (m != MAP_NEVER_FLOWTROUGH && dest->quote) 3368 || (m != CHAR_SPECIAL && dest->quote)
3369 ) { 3369 ) {
3370 b_addqchr(dest, ch, dest->quote); 3370 b_addqchr(dest, ch, dest->quote);
3371 continue; 3371 continue;
3372 } 3372 }
3373 if (m == MAP_IFS_IF_UNQUOTED) { 3373 if (m == CHAR_IFS) {
3374 if (done_word(dest, ctx)) { 3374 if (done_word(dest, ctx)) {
3375 debug_printf_parse("parse_stream return 1: done_word!=0\n"); 3375 debug_printf_parse("parse_stream return 1: done_word!=0\n");
3376 return 1; 3376 return 1;
@@ -3388,7 +3388,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3388 debug_printf_parse("parse_stream return 0: end_trigger char found\n"); 3388 debug_printf_parse("parse_stream return 0: end_trigger char found\n");
3389 return 0; 3389 return 0;
3390 } 3390 }
3391 if (m == MAP_IFS_IF_UNQUOTED) 3391 if (m == CHAR_IFS)
3392 continue; 3392 continue;
3393 switch (ch) { 3393 switch (ch) {
3394 case '#': 3394 case '#':
@@ -3527,28 +3527,28 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3527 return 0; 3527 return 0;
3528} 3528}
3529 3529
3530static void mapset(const char *set, int code) 3530static void set_in_charmap(const char *set, int code)
3531{ 3531{
3532 while (*set) 3532 while (*set)
3533 map[(unsigned char)*set++] = code; 3533 charmap[(unsigned char)*set++] = code;
3534} 3534}
3535 3535
3536static void update_ifs_map(void) 3536static void update_charmap(void)
3537{ 3537{
3538 /* char *ifs and char map[256] are both globals. */ 3538 /* char *ifs and char charmap[256] are both globals. */
3539 ifs = getenv("IFS"); 3539 ifs = getenv("IFS");
3540 if (ifs == NULL) 3540 if (ifs == NULL)
3541 ifs = " \t\n"; 3541 ifs = " \t\n";
3542 /* Precompute a list of 'flow through' behavior so it can be treated 3542 /* Precompute a list of 'flow through' behavior so it can be treated
3543 * quickly up front. Computation is necessary because of IFS. 3543 * quickly up front. Computation is necessary because of IFS.
3544 * Special case handling of IFS == " \t\n" is not implemented. 3544 * Special case handling of IFS == " \t\n" is not implemented.
3545 * The map[] array only really needs two bits each, and on most machines 3545 * The charmap[] array only really needs two bits each,
3546 * that would be faster because of the reduced L1 cache footprint. 3546 * and on most machines that would be faster (reduced L1 cache use).
3547 */ 3547 */
3548 memset(map, MAP_ORDINARY, sizeof(map)); /* most chars flow through always */ 3548 memset(charmap, CHAR_ORDINARY, sizeof(charmap));
3549 mapset("\\$'\"`", MAP_NEVER_FLOWTROUGH); 3549 set_in_charmap("\\$\"`", CHAR_SPECIAL);
3550 mapset("<>;&|(){}#", MAP_FLOWTROUGH_IF_QUOTED); 3550 set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED);
3551 mapset(ifs, MAP_IFS_IF_UNQUOTED); /* also flow through if quoted */ 3551 set_in_charmap(ifs, CHAR_IFS); /* also flow through if quoted */
3552} 3552}
3553 3553
3554/* most recursion does not come through here, the exception is 3554/* most recursion does not come through here, the exception is
@@ -3561,9 +3561,9 @@ static int parse_stream_outer(struct in_str *inp, int parse_flag)
3561 do { 3561 do {
3562 ctx.parse_type = parse_flag; 3562 ctx.parse_type = parse_flag;
3563 initialize_context(&ctx); 3563 initialize_context(&ctx);
3564 update_ifs_map(); 3564 update_charmap();
3565 if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING)) 3565 if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING))
3566 mapset(";$&|", MAP_ORDINARY); 3566 set_in_charmap(";$&|", CHAR_ORDINARY);
3567#if ENABLE_HUSH_INTERACTIVE 3567#if ENABLE_HUSH_INTERACTIVE
3568 inp->promptmode = 1; 3568 inp->promptmode = 1;
3569#endif 3569#endif
@@ -3665,7 +3665,7 @@ int hush_main(int argc, char **argv)
3665 * hush_main(), therefore we cannot rely on the BSS to zero out this 3665 * hush_main(), therefore we cannot rely on the BSS to zero out this
3666 * stuff. Reset these to 0 every time. */ 3666 * stuff. Reset these to 0 every time. */
3667 ifs = NULL; 3667 ifs = NULL;
3668 /* map[] is taken care of with call to update_ifs_map() */ 3668 /* charmap[] is taken care of with call to update_charmap() */
3669 fake_mode = 0; 3669 fake_mode = 0;
3670 close_me_head = NULL; 3670 close_me_head = NULL;
3671#if ENABLE_HUSH_INTERACTIVE 3671#if ENABLE_HUSH_INTERACTIVE