Skip to content

Commit

Permalink
interp: support closing stdin, stdout, and stderr files
Browse files Browse the repository at this point in the history
  • Loading branch information
mvdan committed Oct 19, 2024
1 parent 9482bff commit 7a3cb55
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
24 changes: 24 additions & 0 deletions interp/interp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,26 @@ var runTests = []runTest{
"mkdir a && cd a && echo foo_interp_missing >b && cd .. && cat a/b",
"foo_interp_missing\n",
},
{
"echo foo 2>&-; :",
"foo\n",
},
{
// `>&-` closes stdout or stderr. Note that any writes result in errors.
"echo foo >&- 2>&-; :",
"",
},
{
"echo foo | sed $(read line 2>/dev/null; echo 's/o/a/g')",
"",
},
{
// `<&-` closes stdin, to e.g. ensure that a subshell does not consume
// the standard input shared with the parent shell.
// Note that any reads result in errors.
"echo foo | sed $(exec <&-; read line 2>/dev/null; echo 's/o/a/g')",
"faa\n",
},

// background/wait
{"wait", ""},
Expand Down Expand Up @@ -2841,6 +2861,10 @@ done <<< 2`,
"read </dev/null",
"exit status 1",
},
{
"read 1</dev/null",
"exit status 1",
},
{
"read -X",
"read: invalid option \"-X\"\nexit status 2 #JUSTERR",
Expand Down
20 changes: 19 additions & 1 deletion interp/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -855,12 +855,19 @@ func (r *Runner) redir(ctx context.Context, rd *syntax.Redirect) (io.Closer, err
r.stdin = pr
return pr, nil
}

orig := &r.stdout
if rd.N != nil {
switch rd.N.Value {
case "0":
// Note that the input redirects below always use stdin (0)
// because we don't support anything else right now.
case "1":
// The default for the output redirects below.
case "2":
orig = &r.stderr
default:
panic(fmt.Sprintf("unsupported redirect fd: %v", rd.N.Value))
}
}
arg := r.literal(rd.Word)
Expand All @@ -885,12 +892,23 @@ func (r *Runner) redir(ctx context.Context, rd *syntax.Redirect) (io.Closer, err
*orig = r.stdout
case "2":
*orig = r.stderr
case "-":
*orig = io.Discard // closing the output writer
default:
panic(fmt.Sprintf("unhandled %v arg: %q", rd.Op, arg))
}
return nil, nil
case syntax.RdrIn, syntax.RdrOut, syntax.AppOut,
syntax.RdrAll, syntax.AppAll:
// done further below
// case syntax.DplIn:
case syntax.DplIn:
switch arg {
case "-":
r.stdin = nil // closing the input file
default:
panic(fmt.Sprintf("unhandled %v arg: %q", rd.Op, arg))
}
return nil, nil
default:
panic(fmt.Sprintf("unhandled redirect op: %v", rd.Op))
}
Expand Down

0 comments on commit 7a3cb55

Please sign in to comment.