1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

DockerCli: Check IsTerminal() for both STDIN and STDOUT

`docker events > /tmp/out` should not print control
characters to non-terminal STDOUT.

This addresses commit 26b4a4920a
without creating regression described in issue #6509.

Signed-off-by: Vojtech Vitek (V-Teq) <vvitek@redhat.com>
This commit is contained in:
Vojtech Vitek (V-Teq) 2014-09-10 15:35:48 +02:00
parent 40c7b53791
commit d742c57f53
4 changed files with 50 additions and 32 deletions

View file

@ -22,10 +22,16 @@ type DockerCli struct {
in io.ReadCloser in io.ReadCloser
out io.Writer out io.Writer
err io.Writer err io.Writer
isTerminal bool
terminalFd uintptr
tlsConfig *tls.Config tlsConfig *tls.Config
scheme string scheme string
// inFd holds file descriptor of the client's STDIN, if it's a valid file
inFd uintptr
// outFd holds file descriptor of the client's STDOUT, if it's a valid file
outFd uintptr
// isTerminalIn describes if client's STDIN is a TTY
isTerminalIn bool
// isTerminalOut describes if client's STDOUT is a TTY
isTerminalOut bool
} }
var funcMap = template.FuncMap{ var funcMap = template.FuncMap{
@ -94,8 +100,10 @@ func (cli *DockerCli) LoadConfigFile() (err error) {
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli { func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var ( var (
isTerminal = false inFd uintptr
terminalFd uintptr outFd uintptr
isTerminalIn = false
isTerminalOut = false
scheme = "http" scheme = "http"
) )
@ -105,22 +113,32 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsC
if in != nil { if in != nil {
if file, ok := in.(*os.File); ok { if file, ok := in.(*os.File); ok {
terminalFd = file.Fd() inFd = file.Fd()
isTerminal = term.IsTerminal(terminalFd) isTerminalIn = term.IsTerminal(inFd)
}
}
if out != nil {
if file, ok := out.(*os.File); ok {
outFd = file.Fd()
isTerminalOut = term.IsTerminal(outFd)
} }
} }
if err == nil { if err == nil {
err = out err = out
} }
return &DockerCli{ return &DockerCli{
proto: proto, proto: proto,
addr: addr, addr: addr,
in: in, in: in,
out: out, out: out,
err: err, err: err,
isTerminal: isTerminal, inFd: inFd,
terminalFd: terminalFd, outFd: outFd,
isTerminalIn: isTerminalIn,
isTerminalOut: isTerminalOut,
tlsConfig: tlsConfig, tlsConfig: tlsConfig,
scheme: scheme, scheme: scheme,
} }

View file

@ -277,14 +277,14 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
// the password or email from the config file, so prompt them // the password or email from the config file, so prompt them
if username != authconfig.Username { if username != authconfig.Username {
if password == "" { if password == "" {
oldState, _ := term.SaveState(cli.terminalFd) oldState, _ := term.SaveState(cli.inFd)
fmt.Fprintf(cli.out, "Password: ") fmt.Fprintf(cli.out, "Password: ")
term.DisableEcho(cli.terminalFd, oldState) term.DisableEcho(cli.inFd, oldState)
password = readInput(cli.in, cli.out) password = readInput(cli.in, cli.out)
fmt.Fprint(cli.out, "\n") fmt.Fprint(cli.out, "\n")
term.RestoreTerminal(cli.terminalFd, oldState) term.RestoreTerminal(cli.inFd, oldState)
if password == "" { if password == "" {
return fmt.Errorf("Error : Password Required") return fmt.Errorf("Error : Password Required")
} }
@ -670,7 +670,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
} }
if *openStdin || *attach { if *openStdin || *attach {
if tty && cli.isTerminal { if tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil { if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
log.Errorf("Error monitoring TTY size: %s", err) log.Errorf("Error monitoring TTY size: %s", err)
} }
@ -1822,7 +1822,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
tty = config.GetBool("Tty") tty = config.GetBool("Tty")
) )
if tty && cli.isTerminal { if tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil { if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
log.Debugf("Error monitoring TTY size: %s", err) log.Debugf("Error monitoring TTY size: %s", err)
} }
@ -2247,7 +2247,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
return err return err
} }
if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminal { if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(runResult.Get("Id"), false); err != nil { if err := cli.monitorTtySize(runResult.Get("Id"), false); err != nil {
log.Errorf("Error monitoring TTY size: %s", err) log.Errorf("Error monitoring TTY size: %s", err)
} }
@ -2496,7 +2496,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
} }
} }
if execConfig.Tty && cli.isTerminal { if execConfig.Tty && cli.isTerminalIn {
if err := cli.monitorTtySize(execID, true); err != nil { if err := cli.monitorTtySize(execID, true); err != nil {
log.Errorf("Error monitoring TTY size: %s", err) log.Errorf("Error monitoring TTY size: %s", err)
} }

View file

@ -69,20 +69,20 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
var oldState *term.State var oldState *term.State
if in != nil && setRawTerminal && cli.isTerminal && os.Getenv("NORAW") == "" { if in != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" {
oldState, err = term.SetRawTerminal(cli.terminalFd) oldState, err = term.SetRawTerminal(cli.inFd)
if err != nil { if err != nil {
return err return err
} }
defer term.RestoreTerminal(cli.terminalFd, oldState) defer term.RestoreTerminal(cli.inFd, oldState)
} }
if stdout != nil || stderr != nil { if stdout != nil || stderr != nil {
receiveStdout = utils.Go(func() (err error) { receiveStdout = utils.Go(func() (err error) {
defer func() { defer func() {
if in != nil { if in != nil {
if setRawTerminal && cli.isTerminal { if setRawTerminal && cli.isTerminalIn {
term.RestoreTerminal(cli.terminalFd, oldState) term.RestoreTerminal(cli.inFd, oldState)
} }
// For some reason this Close call blocks on darwin.. // For some reason this Close call blocks on darwin..
// As the client exists right after, simply discard the close // As the client exists right after, simply discard the close
@ -129,7 +129,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
} }
} }
if !cli.isTerminal { if !cli.isTerminalIn {
if err := <-sendStdin; err != nil { if err := <-sendStdin; err != nil {
log.Debugf("Error sendStdin: %s", err) log.Debugf("Error sendStdin: %s", err)
return err return err

View file

@ -168,7 +168,7 @@ func (cli *DockerCli) streamHelper(method, path string, setRawTerminal bool, in
} }
if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") || api.MatchesContentType(resp.Header.Get("Content-Type"), "application/x-json-stream") { if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") || api.MatchesContentType(resp.Header.Get("Content-Type"), "application/x-json-stream") {
return utils.DisplayJSONMessagesStream(resp.Body, stdout, cli.terminalFd, cli.isTerminal) return utils.DisplayJSONMessagesStream(resp.Body, stdout, cli.outFd, cli.isTerminalOut)
} }
if stdout != nil || stderr != nil { if stdout != nil || stderr != nil {
// When TTY is ON, use regular copy // When TTY is ON, use regular copy
@ -252,10 +252,10 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
} }
func (cli *DockerCli) getTtySize() (int, int) { func (cli *DockerCli) getTtySize() (int, int) {
if !cli.isTerminal { if !cli.isTerminalOut {
return 0, 0 return 0, 0
} }
ws, err := term.GetWinsize(cli.terminalFd) ws, err := term.GetWinsize(cli.outFd)
if err != nil { if err != nil {
log.Debugf("Error getting size: %s", err) log.Debugf("Error getting size: %s", err)
if ws == nil { if ws == nil {