@@ -8,14 +8,19 @@ import (
88 "github.com/Sirupsen/logrus"
99 "github.com/docker/cli/cli/command"
1010 "github.com/docker/docker/api/types"
11+ "github.com/docker/docker/pkg/ioutils"
1112 "github.com/docker/docker/pkg/stdcopy"
13+ "github.com/docker/docker/pkg/term"
1214 "golang.org/x/net/context"
1315)
1416
17+ // The default escape key sequence: ctrl-p, ctrl-q
18+ var defaultEscapeKeys = []byte {16 , 17 }
19+
1520// holdHijackedConnection handles copying input to and output from streams to the
1621// connection
1722// nolint: gocyclo
18- func holdHijackedConnection (ctx context.Context , streams command.Streams , tty bool , inputStream io.ReadCloser , outputStream , errorStream io.Writer , resp types.HijackedResponse ) error {
23+ func holdHijackedConnection (ctx context.Context , streams command.Streams , tty bool , detachKeys string , inputStream io.ReadCloser , outputStream , errorStream io.Writer , resp types.HijackedResponse ) error {
1924 var (
2025 err error
2126 restoreOnce sync.Once
@@ -29,6 +34,15 @@ func holdHijackedConnection(ctx context.Context, streams command.Streams, tty bo
2934 restoreTerminal (streams , inputStream )
3035 })
3136 }()
37+
38+ // Wrap the input to detect detach control sequence.
39+ // Use default detach sequence if an invalid sequence is given.
40+ escapeKeys , err := term .ToBytes (detachKeys )
41+ if len (escapeKeys ) == 0 || err != nil {
42+ escapeKeys = defaultEscapeKeys
43+ }
44+
45+ inputStream = ioutils .NewReadCloserWrapper (term .NewEscapeProxy (inputStream , escapeKeys ), inputStream .Close )
3246 }
3347
3448 receiveStdout := make (chan error , 1 )
@@ -54,9 +68,10 @@ func holdHijackedConnection(ctx context.Context, streams command.Streams, tty bo
5468 }
5569
5670 stdinDone := make (chan struct {})
71+ detachedC := make (chan term.EscapeError )
5772 go func () {
5873 if inputStream != nil {
59- io .Copy (resp .Conn , inputStream )
74+ _ , inputErr := io .Copy (resp .Conn , inputStream )
6075 // we should restore the terminal as soon as possible once connection end
6176 // so any following print messages will be in normal type.
6277 if tty {
@@ -65,6 +80,11 @@ func holdHijackedConnection(ctx context.Context, streams command.Streams, tty bo
6580 })
6681 }
6782 logrus .Debug ("[hijack] End of stdin" )
83+
84+ if detached , ok := inputErr .(term.EscapeError ); ok {
85+ detachedC <- detached
86+ return
87+ }
6888 }
6989
7090 if err := resp .CloseWrite (); err != nil {
@@ -90,6 +110,9 @@ func holdHijackedConnection(ctx context.Context, streams command.Streams, tty bo
90110 case <- ctx .Done ():
91111 }
92112 }
113+ case err := <- detachedC :
114+ // Got a detach key sequence.
115+ return err
93116 case <- ctx .Done ():
94117 }
95118
0 commit comments