Date: Fri, 1 Jan 2010 18:17:46 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r201366 - in head: bin/sh tools/regression/bin/sh/expansion Message-ID: <201001011817.o01IHkU4089396@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Fri Jan 1 18:17:46 2010 New Revision: 201366 URL: http://svn.freebsd.org/changeset/base/201366 Log: sh: Fix some bugs with backquoted builtins: - correctly handle error output in $(builtin 2>&1), clarify out1/out2 vs output/errout in the code - treat all builtins as regular builtins so errors do not abort the shell and variable assignments do not persist - respect the caller's INTOFF Some bugs still exist: - expansion errors may still abort the shell - some side effects of expansions and builtins persist Added: head/tools/regression/bin/sh/expansion/cmdsubst1.0 (contents, props changed) Modified: head/bin/sh/error.c head/bin/sh/eval.c head/bin/sh/exec.c head/bin/sh/expand.c head/bin/sh/output.h head/bin/sh/parser.c Modified: head/bin/sh/error.c ============================================================================== --- head/bin/sh/error.c Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/error.c Fri Jan 1 18:17:46 2010 (r201366) @@ -160,8 +160,8 @@ exverror(int cond, const char *msg, va_l #endif if (msg) { if (commandname) - outfmt(&errout, "%s: ", commandname); - doformat(&errout, msg, ap); + outfmt(out2, "%s: ", commandname); + doformat(out2, msg, ap); out2c('\n'); } flushall(); Modified: head/bin/sh/eval.c ============================================================================== --- head/bin/sh/eval.c Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/eval.c Fri Jan 1 18:17:46 2010 (r201366) @@ -646,7 +646,7 @@ evalcommand(union node *cmd, int flags, out2str(ps4val()); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) - outc(' ', &errout); + out2c(' '); p = sp->text; while (*p != '=' && *p != '\0') out2c(*p++); @@ -658,7 +658,7 @@ evalcommand(union node *cmd, int flags, } for (sp = arglist.list ; sp ; sp = sp->next) { if (sep != 0) - outc(' ', &errout); + out2c(' '); /* Disambiguate command looking like assignment. */ if (sp == arglist.list && strchr(sp->text, '=') != NULL && @@ -670,7 +670,7 @@ evalcommand(union node *cmd, int flags, out2qstr(sp->text); sep = ' '; } - outc('\n', &errout); + out2c('\n'); flushout(&errout); } @@ -722,9 +722,8 @@ evalcommand(union node *cmd, int flags, break; if ((cmdentry.u.index = find_builtin(*argv, &cmdentry.special)) < 0) { - outfmt(&errout, "%s: not found\n", *argv); + out2fmt_flush("%s: not found\n", *argv); exitstatus = 127; - flushout(&errout); return; } if (cmdentry.u.index != BLTINCMD) @@ -832,6 +831,7 @@ evalcommand(union node *cmd, int flags, memout.nextc = memout.buf; memout.bufsize = 64; mode |= REDIR_BACKQ; + cmdentry.special = 0; } savecmdname = commandname; savetopfile = getcurrentfile(); @@ -865,20 +865,21 @@ cmddone: } } handler = savehandler; + if (flags == EV_BACKCMD) { + backcmd->buf = memout.buf; + backcmd->nleft = memout.nextc - memout.buf; + memout.buf = NULL; + } if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.special) exraise(e); popfilesupto(savetopfile); - FORCEINTON; + if (flags != EV_BACKCMD) + FORCEINTON; } if (cmdentry.u.index != EXECCMD) popredir(); - if (flags == EV_BACKCMD) { - backcmd->buf = memout.buf; - backcmd->nleft = memout.nextc - memout.buf; - memout.buf = NULL; - } } else { #ifdef DEBUG trputs("normal command: "); trargs(argv); Modified: head/bin/sh/exec.c ============================================================================== --- head/bin/sh/exec.c Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/exec.c Fri Jan 1 18:17:46 2010 (r201366) @@ -255,7 +255,7 @@ hashcmd(int argc __unused, char **argv _ if (cmdp != NULL) printentry(cmdp, verbose); else - outfmt(&errout, "%s: not found\n", name); + outfmt(out2, "%s: not found\n", name); } flushall(); } Modified: head/bin/sh/expand.c ============================================================================== --- head/bin/sh/expand.c Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/expand.c Fri Jan 1 18:17:46 2010 (r201366) @@ -526,7 +526,7 @@ subevalvar(char *p, char *str, int strlo case VSQUESTION: if (*p != CTLENDVAR) { - outfmt(&errout, "%s\n", startp); + outfmt(out2, "%s\n", startp); error((char *)NULL); } error("%.*s: parameter %snot set", (int)(p - str - 1), Modified: head/bin/sh/output.h ============================================================================== --- head/bin/sh/output.h Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/output.h Fri Jan 1 18:17:46 2010 (r201366) @@ -46,11 +46,12 @@ struct output { short flags; }; -extern struct output output; -extern struct output errout; +extern struct output output; /* to fd 1 */ +extern struct output errout; /* to fd 2 */ extern struct output memout; -extern struct output *out1; -extern struct output *out2; +extern struct output *out1; /* &memout if backquote, otherwise &output */ +extern struct output *out2; /* &memout if backquote with 2>&1, otherwise + &errout */ void out1str(const char *); void out1qstr(const char *); Modified: head/bin/sh/parser.c ============================================================================== --- head/bin/sh/parser.c Fri Jan 1 17:30:58 2010 (r201365) +++ head/bin/sh/parser.c Fri Jan 1 18:17:46 2010 (r201366) @@ -1560,8 +1560,8 @@ STATIC void synerror(const char *msg) { if (commandname) - outfmt(&errout, "%s: %d: ", commandname, startlinno); - outfmt(&errout, "Syntax error: %s\n", msg); + outfmt(out2, "%s: %d: ", commandname, startlinno); + outfmt(out2, "Syntax error: %s\n", msg); error((char *)NULL); } Added: head/tools/regression/bin/sh/expansion/cmdsubst1.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/bin/sh/expansion/cmdsubst1.0 Fri Jan 1 18:17:46 2010 (r201366) @@ -0,0 +1,48 @@ +# $FreeBSD$ + +failures=0 + +check() { + if ! eval "[ $* ]"; then + echo "Failed: $*" + : $((failures += 1)) + fi +} + +check '"$(echo abcde)" = "abcde"' +check '"$(echo abcde; :)" = "abcde"' + +check '"$(printf abcde)" = "abcde"' +check '"$(printf abcde; :)" = "abcde"' + +# regular +check '-n "$(umask)"' +check '-n "$(umask; :)"' +check '-n "$(umask 2>&1)"' +check '-n "$(umask 2>&1; :)"' + +# special +check '-n "$(times)"' +check '-n "$(times; :)"' +check '-n "$(times 2>&1)"' +check '-n "$(times 2>&1; :)"' + +# regular +check '".$(umask -@ 2>&1)." = ".umask: Illegal option -@."' +check '".$(umask -@ 2>&1; :)." = ".umask: Illegal option -@."' +check '".$({ umask -@; } 2>&1)." = ".umask: Illegal option -@."' + +# special +check '".$(shift xyz 2>&1)." = ".shift: Illegal number: xyz."' +check '".$(shift xyz 2>&1; :)." = ".shift: Illegal number: xyz."' +check '".$({ shift xyz; } 2>&1)." = ".shift: Illegal number: xyz."' + +v=1 +check '-z "$(v=2 :)"' +check '"$v" = 1' +check '-z "$(v=3)"' +check '"$v" = 1' +check '"$(v=4 eval echo \$v)" = 4' +check '"$v" = 1' + +exit $((failures > 0))
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001011817.o01IHkU4089396>