From owner-svn-src-all@freebsd.org Wed Aug 19 20:31:05 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 06EFD9BEC5B; Wed, 19 Aug 2015 20:31:05 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D71A410F6; Wed, 19 Aug 2015 20:31:04 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t7JKV4lg028452; Wed, 19 Aug 2015 20:31:04 GMT (envelope-from jilles@FreeBSD.org) Received: (from jilles@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t7JKV49G028449; Wed, 19 Aug 2015 20:31:04 GMT (envelope-from jilles@FreeBSD.org) Message-Id: <201508192031.t7JKV49G028449@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jilles set sender to jilles@FreeBSD.org using -f From: Jilles Tjoelker Date: Wed, 19 Aug 2015 20:31:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r286941 - in head: lib/libc/gen tools/regression/lib/libc/gen X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Aug 2015 20:31:05 -0000 Author: jilles Date: Wed Aug 19 20:31:03 2015 New Revision: 286941 URL: https://svnweb.freebsd.org/changeset/base/286941 Log: 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. Modified: head/lib/libc/gen/wordexp.3 head/lib/libc/gen/wordexp.c head/tools/regression/lib/libc/gen/test-wordexp.c Modified: head/lib/libc/gen/wordexp.3 ============================================================================== --- head/lib/libc/gen/wordexp.3 Wed Aug 19 20:10:58 2015 (r286940) +++ head/lib/libc/gen/wordexp.3 Wed Aug 19 20:31:03 2015 (r286941) @@ -131,9 +131,10 @@ argument contains one of the following u .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 subst 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 . Modified: head/lib/libc/gen/wordexp.c ============================================================================== --- head/lib/libc/gen/wordexp.c Wed Aug 19 20:10:58 2015 (r286940) +++ head/lib/libc/gen/wordexp.c Wed Aug 19 20:31:03 2015 (r286941) @@ -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 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 _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 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->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 Modified: head/tools/regression/lib/libc/gen/test-wordexp.c ============================================================================== --- head/tools/regression/lib/libc/gen/test-wordexp.c Wed Aug 19 20:10:58 2015 (r286940) +++ head/tools/regression/lib/libc/gen/test-wordexp.c Wed Aug 19 20:31:03 2015 (r286941) @@ -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;