github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/api/client/hijack.go (about) 1 package client 2 3 import ( 4 "io" 5 "os" 6 7 "github.com/Sirupsen/logrus" 8 "github.com/docker/docker/pkg/stdcopy" 9 "github.com/docker/docker/pkg/term" 10 "github.com/docker/engine-api/types" 11 ) 12 13 func (cli *DockerCli) holdHijackedConnection(setRawTerminal bool, inputStream io.ReadCloser, outputStream, errorStream io.Writer, resp types.HijackedResponse) error { 14 var ( 15 err error 16 oldState *term.State 17 ) 18 if inputStream != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" { 19 oldState, err = term.SetRawTerminal(cli.inFd) 20 if err != nil { 21 return err 22 } 23 defer term.RestoreTerminal(cli.inFd, oldState) 24 } 25 26 receiveStdout := make(chan error, 1) 27 if outputStream != nil || errorStream != nil { 28 go func() { 29 defer func() { 30 if inputStream != nil { 31 if setRawTerminal && cli.isTerminalIn { 32 term.RestoreTerminal(cli.inFd, oldState) 33 } 34 inputStream.Close() 35 } 36 }() 37 38 // When TTY is ON, use regular copy 39 if setRawTerminal && outputStream != nil { 40 _, err = io.Copy(outputStream, resp.Reader) 41 } else { 42 _, err = stdcopy.StdCopy(outputStream, errorStream, resp.Reader) 43 } 44 logrus.Debugf("[hijack] End of stdout") 45 receiveStdout <- err 46 }() 47 } 48 49 stdinDone := make(chan struct{}) 50 go func() { 51 if inputStream != nil { 52 io.Copy(resp.Conn, inputStream) 53 logrus.Debugf("[hijack] End of stdin") 54 } 55 56 if err := resp.CloseWrite(); err != nil { 57 logrus.Debugf("Couldn't send EOF: %s", err) 58 } 59 close(stdinDone) 60 }() 61 62 select { 63 case err := <-receiveStdout: 64 if err != nil { 65 logrus.Debugf("Error receiveStdout: %s", err) 66 return err 67 } 68 case <-stdinDone: 69 if outputStream != nil || errorStream != nil { 70 if err := <-receiveStdout; err != nil { 71 logrus.Debugf("Error receiveStdout: %s", err) 72 return err 73 } 74 } 75 } 76 77 return nil 78 }