github.com/kunnos/engine@v1.13.1/cli/command/in.go (about) 1 package command 2 3 import ( 4 "errors" 5 "io" 6 "os" 7 "runtime" 8 9 "github.com/docker/docker/pkg/term" 10 ) 11 12 // InStream is an input stream used by the DockerCli to read user input 13 type InStream struct { 14 in io.ReadCloser 15 fd uintptr 16 isTerminal bool 17 state *term.State 18 } 19 20 func (i *InStream) Read(p []byte) (int, error) { 21 return i.in.Read(p) 22 } 23 24 // Close implements the Closer interface 25 func (i *InStream) Close() error { 26 return i.in.Close() 27 } 28 29 // FD returns the file descriptor number for this stream 30 func (i *InStream) FD() uintptr { 31 return i.fd 32 } 33 34 // IsTerminal returns true if this stream is connected to a terminal 35 func (i *InStream) IsTerminal() bool { 36 return i.isTerminal 37 } 38 39 // SetRawTerminal sets raw mode on the input terminal 40 func (i *InStream) SetRawTerminal() (err error) { 41 if os.Getenv("NORAW") != "" || !i.isTerminal { 42 return nil 43 } 44 i.state, err = term.SetRawTerminal(i.fd) 45 return err 46 } 47 48 // RestoreTerminal restores normal mode to the terminal 49 func (i *InStream) RestoreTerminal() { 50 if i.state != nil { 51 term.RestoreTerminal(i.fd, i.state) 52 } 53 } 54 55 // CheckTty checks if we are trying to attach to a container tty 56 // from a non-tty client input stream, and if so, returns an error. 57 func (i *InStream) CheckTty(attachStdin, ttyMode bool) error { 58 // In order to attach to a container tty, input stream for the client must 59 // be a tty itself: redirecting or piping the client standard input is 60 // incompatible with `docker run -t`, `docker exec -t` or `docker attach`. 61 if ttyMode && attachStdin && !i.isTerminal { 62 eText := "the input device is not a TTY" 63 if runtime.GOOS == "windows" { 64 return errors.New(eText + ". If you are using mintty, try prefixing the command with 'winpty'") 65 } 66 return errors.New(eText) 67 } 68 return nil 69 } 70 71 // NewInStream returns a new InStream object from a ReadCloser 72 func NewInStream(in io.ReadCloser) *InStream { 73 fd, isTerminal := term.GetFdInfo(in) 74 return &InStream{in: in, fd: fd, isTerminal: isTerminal} 75 }