diff options
author | jilles <jilles@FreeBSD.org> | 2015-08-19 20:31:03 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2015-08-19 20:31:03 +0000 |
commit | 23ea14394056d1cc1eeff8b67732953fc6c60bee (patch) | |
tree | b4e077d645909eff7dcb96ed78b213229629211b /lib/libc | |
parent | 1c9ebc8c01d333f11486321587e573c45b810bf5 (diff) | |
download | FreeBSD-src-23ea14394056d1cc1eeff8b67732953fc6c60bee.zip FreeBSD-src-23ea14394056d1cc1eeff8b67732953fc6c60bee.tar.gz |
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.
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/wordexp.3 | 9 | ||||
-rw-r--r-- | lib/libc/gen/wordexp.c | 41 |
2 files changed, 32 insertions, 18 deletions
diff --git a/lib/libc/gen/wordexp.3 b/lib/libc/gen/wordexp.3 index a564653..2fc20ef 100644 --- a/lib/libc/gen/wordexp.3 +++ b/lib/libc/gen/wordexp.3 @@ -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 . diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c index d0ddcf0..958ddc6 100644 --- a/lib/libc/gen/wordexp.c +++ b/lib/libc/gen/wordexp.c @@ -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 @@ cleanup: 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 |