github.1git.de/docker/cli@v26.1.3+incompatible/cli/streams/in.go (about) 1 package streams 2 3 import ( 4 "errors" 5 "io" 6 "os" 7 "runtime" 8 9 "github.com/moby/term" 10 ) 11 12 // In is an input stream to read user input. It implements [io.ReadCloser] 13 // with additional utilities, such as putting the terminal in raw mode. 14 type In struct { 15 commonStream 16 in io.ReadCloser 17 } 18 19 // Read implements the [io.Reader] interface. 20 func (i *In) Read(p []byte) (int, error) { 21 return i.in.Read(p) 22 } 23 24 // Close implements the [io.Closer] interface. 25 func (i *In) Close() error { 26 return i.in.Close() 27 } 28 29 // SetRawTerminal sets raw mode on the input terminal. It is a no-op if In 30 // is not a TTY, or if the "NORAW" environment variable is set to a non-empty 31 // value. 32 func (i *In) SetRawTerminal() (err error) { 33 if !i.isTerminal || os.Getenv("NORAW") != "" { 34 return nil 35 } 36 i.state, err = term.SetRawTerminal(i.fd) 37 return err 38 } 39 40 // CheckTty checks if we are trying to attach to a container TTY 41 // from a non-TTY client input stream, and if so, returns an error. 42 func (i *In) CheckTty(attachStdin, ttyMode bool) error { 43 // In order to attach to a container tty, input stream for the client must 44 // be a tty itself: redirecting or piping the client standard input is 45 // incompatible with `docker run -t`, `docker exec -t` or `docker attach`. 46 if ttyMode && attachStdin && !i.isTerminal { 47 const eText = "the input device is not a TTY" 48 if runtime.GOOS == "windows" { 49 return errors.New(eText + ". If you are using mintty, try prefixing the command with 'winpty'") 50 } 51 return errors.New(eText) 52 } 53 return nil 54 } 55 56 // NewIn returns a new [In] from an [io.ReadCloser]. 57 func NewIn(in io.ReadCloser) *In { 58 i := &In{in: in} 59 i.fd, i.isTerminal = term.GetFdInfo(in) 60 return i 61 }