diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-16 09:36:55 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-16 09:36:55 +0000 |
commit | 8f6bdb42df745425ba0ac085467105e9cc61c817 (patch) | |
tree | 06e545effca8a1a64a812f19f1cc63e16892e055 /shell/hush.c | |
parent | 418a7fb29b19e42818b5df681c83b3bfc62db3c6 (diff) | |
download | busybox-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.c | 50 |
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 */ |
283 | enum { | 283 | enum { |
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 | }; |
289 | static unsigned char map[256]; | 289 | static unsigned char charmap[256]; |
290 | static const char *ifs; | 290 | static const char *ifs; |
291 | static int fake_mode; | 291 | static int fake_mode; |
292 | static struct close_me *close_me_head; | 292 | static 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 */ |
2316 | static int count_ifs(const char *str) | 2316 | static 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 | ||
3530 | static void mapset(const char *set, int code) | 3530 | static 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 | ||
3536 | static void update_ifs_map(void) | 3536 | static 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 |