diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 16:02:58 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 16:02:58 +0200 |
| commit | 9678636911b39a7adf9b51d5b625cf4dc7e4ac81 (patch) | |
| tree | 75a0790a958a82015b34fc033d6f22f6f6dd3cb2 /shell/hush.c | |
| parent | 34179956f96370f5a53e73073d984d62135cd037 (diff) | |
| download | busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.gz busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.bz2 busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.zip | |
hush: IFS fixes
$ IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
|x|
$ IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
|x|
||
function old new delta
run_pipe 1789 1870 +81
expand_on_ifs 310 361 +51
pseudo_exec_argv 588 591 +3
builtin_local 50 53 +3
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 138/0) Total: 138 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/hush.c')
| -rw-r--r-- | shell/hush.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/shell/hush.c b/shell/hush.c index 248364be2..8e95a26a6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -930,6 +930,7 @@ struct globals { | |||
| 930 | unsigned getopt_count; | 930 | unsigned getopt_count; |
| 931 | #endif | 931 | #endif |
| 932 | const char *ifs; | 932 | const char *ifs; |
| 933 | char *ifs_whitespace; /* = G.ifs or malloced */ | ||
| 933 | const char *cwd; | 934 | const char *cwd; |
| 934 | struct variable *top_var; | 935 | struct variable *top_var; |
| 935 | char **expanded_assignments; | 936 | char **expanded_assignments; |
| @@ -5696,10 +5697,20 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
| 5696 | 5697 | ||
| 5697 | /* We know str here points to at least one IFS char */ | 5698 | /* We know str here points to at least one IFS char */ |
| 5698 | last_is_ifs = 1; | 5699 | last_is_ifs = 1; |
| 5699 | str += strspn(str, G.ifs); /* skip IFS chars */ | 5700 | str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */ |
| 5700 | if (!*str) /* EOL - do not finalize word */ | 5701 | if (!*str) /* EOL - do not finalize word */ |
| 5701 | break; | 5702 | break; |
| 5702 | 5703 | ||
| 5704 | if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */ | ||
| 5705 | && strchr(G.ifs, *str) /* the second check would fail */ | ||
| 5706 | ) { | ||
| 5707 | /* This is a non-whitespace $IFS char */ | ||
| 5708 | /* Skip it and IFS whitespace chars, start new word */ | ||
| 5709 | str++; | ||
| 5710 | str += strspn(str, G.ifs_whitespace); | ||
| 5711 | goto new_word; | ||
| 5712 | } | ||
| 5713 | |||
| 5703 | /* Start new word... but not always! */ | 5714 | /* Start new word... but not always! */ |
| 5704 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ | 5715 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ |
| 5705 | if (output->has_quoted_part | 5716 | if (output->has_quoted_part |
| @@ -5710,6 +5721,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
| 5710 | */ | 5721 | */ |
| 5711 | || (n > 0 && output->data[output->length - 1]) | 5722 | || (n > 0 && output->data[output->length - 1]) |
| 5712 | ) { | 5723 | ) { |
| 5724 | new_word: | ||
| 5713 | o_addchr(output, '\0'); | 5725 | o_addchr(output, '\0'); |
| 5714 | debug_print_list("expand_on_ifs", output, n); | 5726 | debug_print_list("expand_on_ifs", output, n); |
| 5715 | n = o_save_ptr(output, n); | 5727 | n = o_save_ptr(output, n); |
| @@ -8283,9 +8295,31 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
| 8283 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" | 8295 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" |
| 8284 | * Result should be 3 lines: q w e, qwe, q w e | 8296 | * Result should be 3 lines: q w e, qwe, q w e |
| 8285 | */ | 8297 | */ |
| 8298 | if (G.ifs_whitespace != G.ifs) | ||
| 8299 | free(G.ifs_whitespace); | ||
| 8286 | G.ifs = get_local_var_value("IFS"); | 8300 | G.ifs = get_local_var_value("IFS"); |
| 8287 | if (!G.ifs) | 8301 | if (G.ifs) { |
| 8302 | char *p; | ||
| 8303 | G.ifs_whitespace = (char*)G.ifs; | ||
| 8304 | p = skip_whitespace(G.ifs); | ||
| 8305 | if (*p) { | ||
| 8306 | /* Not all $IFS is whitespace */ | ||
| 8307 | char *d; | ||
| 8308 | int len = p - G.ifs; | ||
| 8309 | p = skip_non_whitespace(p); | ||
| 8310 | G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */ | ||
| 8311 | d = mempcpy(G.ifs_whitespace, G.ifs, len); | ||
| 8312 | while (*p) { | ||
| 8313 | if (isspace(*p)) | ||
| 8314 | *d++ = *p; | ||
| 8315 | p++; | ||
| 8316 | } | ||
| 8317 | *d = '\0'; | ||
| 8318 | } | ||
| 8319 | } else { | ||
| 8288 | G.ifs = defifs; | 8320 | G.ifs = defifs; |
| 8321 | G.ifs_whitespace = (char*)G.ifs; | ||
| 8322 | } | ||
| 8289 | 8323 | ||
| 8290 | IF_HUSH_JOB(pi->pgrp = -1;) | 8324 | IF_HUSH_JOB(pi->pgrp = -1;) |
| 8291 | pi->stopped_cmds = 0; | 8325 | pi->stopped_cmds = 0; |
