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
This commit is contained in:
parent
c8054a6197
commit
f7cc73afc8
@ -160,8 +160,8 @@ exverror(int cond, const char *msg, va_list ap)
|
||||
#endif
|
||||
if (msg) {
|
||||
if (commandname)
|
||||
outfmt(&errout, "%s: ", commandname);
|
||||
doformat(&errout, msg, ap);
|
||||
outfmt(out2, "%s: ", commandname);
|
||||
doformat(out2, msg, ap);
|
||||
out2c('\n');
|
||||
}
|
||||
flushall();
|
||||
|
@ -646,7 +646,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
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, struct backcmd *backcmd)
|
||||
}
|
||||
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, struct backcmd *backcmd)
|
||||
out2qstr(sp->text);
|
||||
sep = ' ';
|
||||
}
|
||||
outc('\n', &errout);
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
|
||||
@ -722,9 +722,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
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, struct backcmd *backcmd)
|
||||
memout.nextc = memout.buf;
|
||||
memout.bufsize = 64;
|
||||
mode |= REDIR_BACKQ;
|
||||
cmdentry.special = 0;
|
||||
}
|
||||
savecmdname = commandname;
|
||||
savetopfile = getcurrentfile();
|
||||
@ -865,20 +865,21 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
}
|
||||
}
|
||||
handler = savehandler;
|
||||
if (e != -1) {
|
||||
if ((e != EXERROR && e != EXEXEC)
|
||||
|| cmdentry.special)
|
||||
exraise(e);
|
||||
popfilesupto(savetopfile);
|
||||
FORCEINTON;
|
||||
}
|
||||
if (cmdentry.u.index != EXECCMD)
|
||||
popredir();
|
||||
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);
|
||||
if (flags != EV_BACKCMD)
|
||||
FORCEINTON;
|
||||
}
|
||||
if (cmdentry.u.index != EXECCMD)
|
||||
popredir();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
trputs("normal command: "); trargs(argv);
|
||||
|
@ -255,7 +255,7 @@ hashcmd(int argc __unused, char **argv __unused)
|
||||
if (cmdp != NULL)
|
||||
printentry(cmdp, verbose);
|
||||
else
|
||||
outfmt(&errout, "%s: not found\n", name);
|
||||
outfmt(out2, "%s: not found\n", name);
|
||||
}
|
||||
flushall();
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
|
||||
|
||||
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),
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
48
tools/regression/bin/sh/expansion/cmdsubst1.0
Normal file
48
tools/regression/bin/sh/expansion/cmdsubst1.0
Normal file
@ -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))
|
Loading…
Reference in New Issue
Block a user