-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix [ -t1 ] inside a command substitution
Another non-forking subshell bug involving `[ -t 1 ]` being true when it should be false. Fixes #1079
- Loading branch information
1 parent
6cd0b41
commit 8e1e405
Showing
6 changed files
with
79 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,8 +92,8 @@ struct test { | |
}; | ||
|
||
static_fn char *nxtarg(struct test *, int); | ||
static_fn int eval_expr(struct test *, int); | ||
static_fn int eval_e3(struct test *); | ||
static_fn int eval_expr(Shell_t *shp, struct test *, int); | ||
static_fn int eval_e3(Shell_t *shp, struct test *); | ||
|
||
static_fn int test_strmatch(Shell_t *shp, const char *str, const char *pat) { | ||
int match[2 * (MATCH_MAX + 1)], n; | ||
|
@@ -223,7 +223,7 @@ int b_test(int argc, char *argv[], Shbltin_t *context) { | |
default: { break; } | ||
} | ||
tdata.ac = argc; | ||
result = !eval_expr(&tdata, 0); | ||
result = !eval_expr(shp, &tdata, 0); | ||
|
||
done: | ||
sh_popcontext(shp, &buff); | ||
|
@@ -236,11 +236,11 @@ int b_test(int argc, char *argv[], Shbltin_t *context) { | |
// Flag is 1 when in parenthesis. | ||
// Flag is 2 when evaluating -a. | ||
// | ||
static_fn int eval_expr(struct test *tp, int flag) { | ||
static_fn int eval_expr(Shell_t *shp, struct test *tp, int flag) { | ||
int r; | ||
char *p; | ||
|
||
r = eval_e3(tp); | ||
r = eval_e3(shp, tp); | ||
while (tp->ap < tp->ac) { | ||
p = nxtarg(tp, 0); | ||
// Check for -o and -a. | ||
|
@@ -254,10 +254,10 @@ static_fn int eval_expr(struct test *tp, int flag) { | |
tp->ap--; | ||
break; | ||
} | ||
r |= eval_expr(tp, 3); | ||
r |= eval_expr(shp, tp, 3); | ||
continue; | ||
} else if (*p == 'a') { | ||
r &= eval_expr(tp, 2); | ||
r &= eval_expr(shp, tp, 2); | ||
continue; | ||
} | ||
} | ||
|
@@ -280,15 +280,15 @@ static_fn char *nxtarg(struct test *tp, int mt) { | |
return tp->av[tp->ap++]; | ||
} | ||
|
||
static_fn int eval_e3(struct test *tp) { | ||
static_fn int eval_e3(Shell_t *shp, struct test *tp) { | ||
char *arg, *cp; | ||
int op; | ||
char *binop; | ||
|
||
arg = nxtarg(tp, 0); | ||
if (c_eq(arg, '!')) return !eval_e3(tp); | ||
if (c_eq(arg, '!')) return !eval_e3(shp, tp); | ||
if (c_eq(arg, '(')) { | ||
op = eval_expr(tp, 1); | ||
op = eval_expr(shp, tp, 1); | ||
cp = nxtarg(tp, 0); | ||
if (!cp || !c_eq(cp, ')')) { | ||
errormsg(SH_DICT, ERROR_exit(2), e_missing, "')'"); | ||
|
@@ -301,11 +301,14 @@ static_fn int eval_e3(struct test *tp) { | |
if (c2_eq(arg, '-', 't')) { | ||
if (cp) { | ||
op = strtol(cp, &binop, 10); | ||
return *binop ? 0 : tty_check(op); | ||
if (*binop) return 0; | ||
if (shp->subshell && op == STDOUT_FILENO) return 0; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
gordonwoodhull
Contributor
|
||
return tty_check(op); | ||
} | ||
// Test -t with no arguments. | ||
tp->ap--; | ||
return tty_check(1); | ||
if (shp->subshell) return 0; | ||
return tty_check(STDOUT_FILENO); | ||
} | ||
if (*arg == '-' && arg[2] == 0) { | ||
op = arg[1]; | ||
|
@@ -441,7 +444,9 @@ int test_unop(Shell_t *shp, int op, const char *arg) { | |
case 't': { | ||
char *last; | ||
op = strtol(arg, &last, 10); | ||
return *last ? 0 : tty_check(op); | ||
if (*last) return 0; | ||
if (shp->subshell && op == STDOUT_FILENO) return 0; | ||
return tty_check(op); | ||
} | ||
case 'v': | ||
case 'R': { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
stdin is a terminal device | ||
stdout is a terminal device | ||
-t1 in comsub works correctly | ||
-t1 in comsub with exec >/dev/tty works correctly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is broken -- it simply always returns true for
[ -t 1 ]
if we're in a virtual/non-forked subshell, so it avoids doing the test altogether and returns a possibly false result.(edit 1 Sep) Actually, I was partially wrong. On ksh93, command substitutions always fork when redirecting standard output within them. Forking (counter-intuitively) resets
shp->subshell
to zero. Consequently, it is safe to return false (0) if bothshp->subshell
andshp->comsub
are set. This is a fix I'm going to apply to 93u+m now, but in a different place (thetty_check()
function).