Fix variable expansion within commands

* src/wordsplit.c (_wsplt_seterr): New static function.  Use instead
of assigning value to ws_errno.
(coalesce_segment): Propagate _WSNF_QUOTE flag to the resulting node.
(wordsplit_process_list): Coalesce the list before running
command expansion.
* tests/testsuite.at: Test wordsplit first.  If it fails, most other
tests will fail too.
* tests/wordsplit.at: Test command expansion.
This commit is contained in:
Sergey Poznyakoff 2014-10-23 15:35:40 +03:00
parent 4650905537
commit 6da71ddacb
2 changed files with 136 additions and 33 deletions

View file

@ -74,6 +74,15 @@ _wsplt_error (const char *fmt, ...)
static void wordsplit_free_nodes (struct wordsplit *);
static int
_wsplt_seterr (struct wordsplit *wsp, int ec)
{
wsp->ws_errno = ec;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return ec;
}
static int
_wsplt_nomem (struct wordsplit *wsp)
{
@ -123,10 +132,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
if (!(wsp->ws_flags & WRDSF_NOVAR)
&& !(wsp->ws_flags & (WRDSF_ENV | WRDSF_GETVAR)))
{
_wsplt_seterr (wsp, WRDSE_USAGE);
errno = EINVAL;
wsp->ws_errno = WRDSE_USAGE;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return wsp->ws_errno;
}
@ -134,10 +141,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
{
if (!wsp->ws_command)
{
_wsplt_seterr (wsp, WRDSE_USAGE);
errno = EINVAL;
wsp->ws_errno = WRDSE_USAGE;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return wsp->ws_errno;
}
}
@ -464,6 +469,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
cur += slen;
if (p != node)
{
node->flags |= p->flags & _WSNF_QUOTE;
wsnode_remove (wsp, p);
stop = p == end;
wsnode_free (p);
@ -741,10 +747,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
defstr = str + i + 1;
if (find_closing_paren (str, i + 1, len, &j, "{}"))
{
wsp->ws_errno = WRDSE_CBRACE;
return 1;
}
return _wsplt_seterr (wsp, WRDSE_CBRACE);
*pend = str + j;
}
else if (str[i] == '}')
@ -752,10 +755,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
*pend = str + i;
}
else
{
wsp->ws_errno = WRDSE_CBRACE;
return 1;
}
return _wsplt_seterr (wsp, WRDSE_CBRACE);
}
else
{
@ -805,9 +805,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
wsp->ws_usererr = value;
/* fall through */
default:
wsp->ws_errno = rc;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
_wsplt_seterr (wsp, rc);
return 1;
}
}
@ -841,9 +839,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
}
else if (wsp->ws_flags & WRDSF_UNDEF)
{
wsp->ws_errno = WRDSE_UNDEF;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
_wsplt_seterr (wsp, WRDSE_UNDEF);
return 1;
}
else
@ -1067,7 +1063,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
if (find_closing_paren (str, 0, len, &j, "()"))
{
wsp->ws_errno = WRDSE_CBRACE;
_wsplt_seterr (wsp, WRDSE_CBRACE);
return 1;
}
@ -1091,9 +1087,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
{
if (rc == WRDSE_USERERR)
wsp->ws_usererr = value;
wsp->ws_errno = rc;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
_wsplt_seterr (wsp, rc);
return 1;
}
@ -1298,9 +1292,7 @@ scan_qstring (struct wordsplit *wsp, size_t start, size_t * end)
else
{
wsp->ws_endp = start;
wsp->ws_errno = WRDSE_QUOTE;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
_wsplt_seterr (wsp, WRDSE_QUOTE);
return _WRDS_ERR;
}
return 0;
@ -1672,6 +1664,15 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
if (!(wsp->ws_flags & WRDSF_NOCMD))
{
if (wsnode_coalesce (wsp))
return wsp->ws_errno;
if (wsp->ws_flags & WRDSF_SHOWDBG)
{
wsp->ws_debug ("Coalesced list:");
wordsplit_dump_nodes (wsp);
}
if (wordsplit_cmdexp (wsp))
{
wordsplit_free_nodes (wsp);
@ -1723,12 +1724,7 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
start = skip_delim (wsp);
if (wsp->ws_endp == wsp->ws_len)
{
wsp->ws_errno = WRDSE_NOINPUT;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return wsp->ws_errno;
}
return _wsplt_seterr (wsp, WRDSE_NOINPUT);
cmdptr = wsp->ws_input + wsp->ws_endp;
cmdlen = wsp->ws_len - wsp->ws_endp;

View file

@ -538,4 +538,111 @@ TESTWSP([getvar, alternate value],[wsp-var wsp-var23 wsp-alt wsp-alt02 wsp-getva
1: isset
])
dnl Something that doesn't fit into TESTWSP
AT_SETUP([simple command expansion])
AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-1 wsp50])
AT_CHECK([
mkdir dir
> dir/file
wsp -nocmd <<'EOT'
begin $(find dir) end
EOT
],
[0],
[NF: 4
0: begin
1: dir
2: dir/file
3: end
])
AT_CLEANUP
AT_SETUP([quoted command expansion])
AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-2 wsp51])
AT_CHECK([
mkdir dir
> dir/file
wsp -nocmd <<'EOT'
begin "$(find dir)" end
EOT
],
[0],
[NF: 3
0: begin
1: "dir dir/file"
2: end
])
AT_CLEANUP
AT_SETUP([coalesced command expansion])
AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-3 wsp52])
AT_CHECK([
mkdir dir
> dir/file
wsp -nocmd <<'EOT'
begin($(find dir))end
EOT
],
[0],
[NF: 2
0: begin(dir
1: dir/file)end
])
AT_CLEANUP
AT_SETUP([quoted coalesced command expansion])
AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-4 wsp53])
AT_CHECK([
mkdir dir
> dir/file
wsp -nocmd <<'EOT'
"begin($(find dir))end"
EOT
],
[0],
[NF: 1
0: "begin(dir dir/file)end"
])
AT_CLEANUP
AT_SETUP([variable and command expansion])
AT_KEYWORDS([wordsplit wsp wsp-var wsp-var24 wsp-cmd wsp-cmd-5 wsp54])
AT_CHECK([
mkdir dir
> dir/file
DIR=dir wsp -nocmd -novar<<'EOT'
begin $(find $DIR) end
EOT
],
[0],
[NF: 4
0: begin
1: dir
2: dir/file
3: end
])
AT_CLEANUP
AT_SETUP([variable and command expansion in quotes])
AT_KEYWORDS([wordsplit wsp wsp-var wsp-var25 wsp-cmd wsp-cmd-6 wsp55])
AT_CHECK([
mkdir dir
> dir/file
DIR=dir wsp -nocmd -novar<<'EOT'
"begin($(find $DIR))end"
EOT
],
[0],
[NF: 1
0: "begin(dir dir/file)end"
])
AT_CLEANUP
m4_popdef([TESTWSP])