summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-16 10:39:24 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-16 10:39:24 +0000
commit1f4cf517f5803b0e300906c487d365a331122091 (patch)
tree8ca30e71e1c0d7cb6f3b64fd9911a85c615170e8
parent8f6bdb42df745425ba0ac085467105e9cc61c817 (diff)
hush: fix expansion of quoted $VAR, $* and $@
-rw-r--r--shell/hush.c45
-rw-r--r--shell/hush_test/hush-bugs/quote3.right5
-rwxr-xr-xshell/hush_test/hush-bugs/quote3.tests4
-rw-r--r--shell/hush_test/hush-bugs/starquoted.right1
-rwxr-xr-xshell/hush_test/hush-bugs/starquoted.tests4
-rw-r--r--shell/hush_test/hush-parsing/quote4.right1
-rwxr-xr-xshell/hush_test/hush-parsing/quote4.tests2
-rw-r--r--shell/hush_test/hush-parsing/starquoted.right8
-rwxr-xr-xshell/hush_test/hush-parsing/starquoted.tests8
9 files changed, 51 insertions, 27 deletions
diff --git a/shell/hush.c b/shell/hush.c
index e49c0c989..e3dd6663e 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2425,6 +2425,7 @@ static int expand_on_ifs(char **list, int n, char **posp, const char *str)
static int expand_vars_to_list(char **list, int n, char **posp, char *arg)
{
char first_ch, ored_ch;
+ int i;
const char *val;
char *p;
char *pos = *posp;
@@ -2462,8 +2463,8 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg)
break;
case '*':
case '@':
+ i = 1;
if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
- int i = 1;
while (i < global_argc) {
n = expand_on_ifs(list, n, &pos, global_argv[i]);
debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1);
@@ -2478,16 +2479,33 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg)
}
}
} else if (first_ch == ('@'|0x80)) { /* quoted $@ */
- /* TODO */
- } else { /* quoted $* */
- /* TODO */
+ while (1) {
+ strcpy(pos, global_argv[i]);
+ pos += strlen(global_argv[i]);
+ if (++i >= global_argc)
+ break;
+ *pos++ = '\0';
+ if (n) debug_printf_expand("expand_vars_to_list 3 finalized list[%d]=%p '%s' "
+ "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
+ strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
+ list[n++] = pos;
+ }
+ } else { /* quoted $*: add as one word */
+ while (1) {
+ strcpy(pos, global_argv[i]);
+ pos += strlen(global_argv[i]);
+ if (++i >= global_argc)
+ break;
+ if (ifs[0])
+ *pos++ = ifs[0];
+ }
}
break;
default:
*p = '\0';
arg[0] = first_ch & 0x7f;
if (isdigit(arg[0])) {
- int i = xatoi_u(arg);
+ i = xatoi_u(arg);
val = NULL;
if (i < global_argc)
val = global_argv[i];
@@ -2495,12 +2513,12 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg)
val = lookup_param(arg);
arg[0] = first_ch;
*p = SPECIAL_VAR_SYMBOL;
- if (!(first_ch & 0x80)) { /* unquoted var */
+ if (!(first_ch & 0x80)) { /* unquoted $VAR */
if (val) {
n = expand_on_ifs(list, n, &pos, val);
val = NULL;
}
- }
+ } /* else: quoted $VAR, val will be appended at pos */
}
if (val) {
strcpy(pos, val);
@@ -3268,18 +3286,18 @@ static char* make_string(char **inp)
/* return code: 0 for OK, 1 for syntax error */
static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
{
-// int i;
-// char sep[] = " ";
int ch = b_peek(input); /* first character after the $ */
+ unsigned char quote_mask = dest->quote ? 0x80 : 0;
debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
- if (isalpha(ch) || ch == '?') {
+ if (isalpha(ch)) {
b_addchr(dest, SPECIAL_VAR_SYMBOL);
ctx->child->sp++;
while (1) {
debug_printf_parse(": '%c'\n", ch);
b_getch(input);
- b_addchr(dest, ch);
+ b_addchr(dest, ch | quote_mask);
+ quote_mask = 0;
ch = b_peek(input);
if (!isalnum(ch) && ch != '_')
break;
@@ -3291,7 +3309,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
ctx->child->sp++;
debug_printf_parse(": '%c'\n", ch);
b_getch(input);
- b_addchr(dest, ch);
+ b_addchr(dest, ch | quote_mask);
b_addchr(dest, SPECIAL_VAR_SYMBOL);
} else switch (ch) {
case '$': /* pid */
@@ -3316,7 +3334,8 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
if (ch == '}')
break;
debug_printf_parse(": '%c'\n", ch);
- b_addchr(dest, ch);
+ b_addchr(dest, ch | quote_mask);
+ quote_mask = 0;
}
b_addchr(dest, SPECIAL_VAR_SYMBOL);
break;
diff --git a/shell/hush_test/hush-bugs/quote3.right b/shell/hush_test/hush-bugs/quote3.right
index 11443f54b..069a46e8f 100644
--- a/shell/hush_test/hush-bugs/quote3.right
+++ b/shell/hush_test/hush-bugs/quote3.right
@@ -1,8 +1,3 @@
Testing: in $empty""
..
-Testing: in "$*"
-.abc d e.
-Testing: in "$@"
-.abc.
-.d e.
Finished
diff --git a/shell/hush_test/hush-bugs/quote3.tests b/shell/hush_test/hush-bugs/quote3.tests
index c52e040cc..075e78570 100755
--- a/shell/hush_test/hush-bugs/quote3.tests
+++ b/shell/hush_test/hush-bugs/quote3.tests
@@ -5,8 +5,4 @@ fi
echo 'Testing: in $empty""'
empty=''
for a in $empty""; do echo ".$a."; done
-echo 'Testing: in "$*"'
-for a in "$*"; do echo ".$a."; done
-echo 'Testing: in "$@"'
-for a in "$@"; do echo ".$a."; done
echo Finished
diff --git a/shell/hush_test/hush-bugs/starquoted.right b/shell/hush_test/hush-bugs/starquoted.right
deleted file mode 100644
index fedaf4805..000000000
--- a/shell/hush_test/hush-bugs/starquoted.right
+++ /dev/null
@@ -1 +0,0 @@
-.1 abc d e f.
diff --git a/shell/hush_test/hush-bugs/starquoted.tests b/shell/hush_test/hush-bugs/starquoted.tests
deleted file mode 100755
index 3be2026b7..000000000
--- a/shell/hush_test/hush-bugs/starquoted.tests
+++ /dev/null
@@ -1,4 +0,0 @@
-if test $# = 0; then
- exec "$THIS_SH" starquoted.tests 1 abc 'd e f'
-fi
-for a in "$*"; do echo ".$a."; done
diff --git a/shell/hush_test/hush-parsing/quote4.right b/shell/hush_test/hush-parsing/quote4.right
new file mode 100644
index 000000000..b2901ea97
--- /dev/null
+++ b/shell/hush_test/hush-parsing/quote4.right
@@ -0,0 +1 @@
+a b
diff --git a/shell/hush_test/hush-parsing/quote4.tests b/shell/hush_test/hush-parsing/quote4.tests
new file mode 100755
index 000000000..f1dabfa54
--- /dev/null
+++ b/shell/hush_test/hush-parsing/quote4.tests
@@ -0,0 +1,2 @@
+a_b='a b'
+echo "$a_b"
diff --git a/shell/hush_test/hush-parsing/starquoted.right b/shell/hush_test/hush-parsing/starquoted.right
new file mode 100644
index 000000000..b56323fe1
--- /dev/null
+++ b/shell/hush_test/hush-parsing/starquoted.right
@@ -0,0 +1,8 @@
+.1 abc d e f.
+.1.
+.abc.
+.d e f.
+.-1 abc d e f-.
+.-1.
+.abc.
+.d e f-.
diff --git a/shell/hush_test/hush-parsing/starquoted.tests b/shell/hush_test/hush-parsing/starquoted.tests
new file mode 100755
index 000000000..2fe49b1cd
--- /dev/null
+++ b/shell/hush_test/hush-parsing/starquoted.tests
@@ -0,0 +1,8 @@
+if test $# = 0; then
+ exec "$THIS_SH" "$0" 1 abc 'd e f'
+fi
+
+for a in "$*"; do echo ".$a."; done
+for a in "$@"; do echo ".$a."; done
+for a in "-$*-"; do echo ".$a."; done
+for a in "-$@-"; do echo ".$a."; done