wordexp(): Improve some error codes.

Distinguish between WRDE_BADVAL and WRDE_SYNTAX based on when the error
occurred (parsing or execution), not based on whether WRDE_UNDEF was passed.

Also, return WRDE_NOSPACE for a few more unexpected results from sh.
This commit is contained in:
Jilles Tjoelker 2015-08-19 20:31:03 +00:00
parent b38fbc2e54
commit 89cead337a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=286941
3 changed files with 41 additions and 18 deletions

View file

@ -131,9 +131,10 @@ argument contains one of the following unquoted characters:
.Ql { ,
.Ql } .
.It Dv WRDE_BADVAL
An attempt was made to expand an undefined shell variable and
An error after successful parsing,
such as an attempt to expand an undefined shell variable with
.Dv WRDE_UNDEF
is set in
set in
.Fa flags .
.It Dv WRDE_CMDSUB
An attempt was made to use command substitution and
@ -141,7 +142,9 @@ An attempt was made to use command substitution and
is set in
.Fa flags .
.It Dv WRDE_NOSPACE
Not enough memory to store the result.
Not enough memory to store the result or
an error during
.Xr fork 2 .
.It Dv WRDE_SYNTAX
Shell syntax error in
.Fa words .

View file

@ -103,8 +103,7 @@ static int
we_askshell(const char *words, wordexp_t *we, int flags)
{
int pdes[2]; /* Pipe to child */
char bbuf[9]; /* Buffer for byte count */
char wbuf[9]; /* Buffer for word count */
char buf[18]; /* Buffer for byte and word count */
long nwords, nbytes; /* Number of words, bytes from child */
long i; /* Handy integer */
size_t sofs; /* Offset into we->we_strings */
@ -119,6 +118,7 @@ we_askshell(const char *words, wordexp_t *we, int flags)
char **nwv; /* Temporary for realloc() */
sigset_t newsigblock, oldsigblock;
const char *ifs;
char save;
serrno = errno;
ifs = getenv("IFS");
@ -146,8 +146,9 @@ we_askshell(const char *words, wordexp_t *we, int flags)
_fcntl(pdes[1], F_SETFD, 0)) < 0)
_exit(1);
execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u",
"-c", "IFS=$1;eval \"$2\";eval \"set -- $3\";IFS=;a=\"$*\";"
"printf '%08x' \"$#\" \"${#a}\";printf '%s\\0' \"$@\"",
"-c", "IFS=$1;eval \"$2\";eval \"echo;set -- $3\";"
"IFS=;a=\"$*\";printf '%08x' \"$#\" \"${#a}\";"
"printf '%s\\0' \"$@\"",
"",
ifs != NULL ? ifs : " \t\n",
flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", words,
@ -157,20 +158,30 @@ we_askshell(const char *words, wordexp_t *we, int flags)
/*
* We are the parent; read the output of the shell wordexp function,
* which is a 32-bit hexadecimal word count, a 32-bit hexadecimal
* byte count (not including terminating null bytes), followed by
* the expanded words separated by nulls.
* which is a byte indicating that the words were parsed successfully,
* a 32-bit hexadecimal word count, a 32-bit hexadecimal byte count
* (not including terminating null bytes), followed by the expanded
* words separated by nulls.
*/
_close(pdes[1]);
if (we_read_fully(pdes[0], wbuf, 8) != 8 ||
we_read_fully(pdes[0], bbuf, 8) != 8) {
error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
switch (we_read_fully(pdes[0], buf, 17)) {
case 1:
error = WRDE_BADVAL;
serrno = errno;
goto cleanup;
case 17:
break;
default:
error = WRDE_SYNTAX;
serrno = errno;
goto cleanup;
}
wbuf[8] = bbuf[8] = '\0';
nwords = strtol(wbuf, NULL, 16);
nbytes = strtol(bbuf, NULL, 16) + nwords;
save = buf[9];
buf[9] = '\0';
nwords = strtol(buf + 1, NULL, 16);
buf[9] = save;
buf[17] = '\0';
nbytes = strtol(buf + 9, NULL, 16) + nwords;
/*
* Allocate or reallocate (when flags & WRDE_APPEND) the word vector
@ -200,7 +211,7 @@ we_askshell(const char *words, wordexp_t *we, int flags)
we->we_strings = nstrings;
if (we_read_fully(pdes[0], we->we_strings + sofs, nbytes) != nbytes) {
error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
error = WRDE_NOSPACE; /* abort for unknown reason */
serrno = errno;
goto cleanup;
}
@ -217,7 +228,7 @@ we_askshell(const char *words, wordexp_t *we, int flags)
return (error);
}
if (wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
return (flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX);
return (WRDE_NOSPACE); /* abort for unknown reason */
/*
* Break the null-terminated expanded word strings out into

View file

@ -206,6 +206,15 @@ main(int argc, char *argv[])
assert(strcmp(we.we_wordv[0], "\\") == 0);
assert(we.we_wordv[1] == NULL);
wordfree(&we);
/* Two syntax errors that are not detected by the current we_check(). */
r = wordexp("${IFS:+'}", &we, 0);
assert(r == WRDE_SYNTAX);
r = wordexp("${IFS:+'}", &we, WRDE_UNDEF);
assert(r == WRDE_SYNTAX);
r = wordexp("$(case)", &we, 0);
assert(r == WRDE_SYNTAX);
r = wordexp("$(case)", &we, WRDE_UNDEF);
assert(r == WRDE_SYNTAX);
/* With a SIGCHLD handler that reaps all zombies. */
sa.sa_flags = 0;