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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to