github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/adapter/terminal_linux.go (about) 1 package adapter 2 3 import ( 4 "bufio" 5 "context" 6 "fmt" 7 "os" 8 9 "github.com/containers/libpod/libpod" 10 "github.com/containers/libpod/libpod/define" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 "golang.org/x/crypto/ssh/terminal" 14 "k8s.io/client-go/tools/remotecommand" 15 ) 16 17 // ExecAttachCtr execs and attaches to a container 18 func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, tty, privileged bool, env map[string]string, cmd []string, user, workDir string, streams *define.AttachStreams, preserveFDs uint, detachKeys string) (int, error) { 19 resize := make(chan remotecommand.TerminalSize) 20 haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) 21 22 // Check if we are attached to a terminal. If we are, generate resize 23 // events, and set the terminal to raw mode 24 if haveTerminal && tty { 25 cancel, oldTermState, err := handleTerminalAttach(ctx, resize) 26 if err != nil { 27 return -1, err 28 } 29 defer cancel() 30 defer func() { 31 if err := restoreTerminal(oldTermState); err != nil { 32 logrus.Errorf("unable to restore terminal: %q", err) 33 } 34 }() 35 } 36 37 execConfig := new(libpod.ExecConfig) 38 execConfig.Command = cmd 39 execConfig.Terminal = tty 40 execConfig.Privileged = privileged 41 execConfig.Environment = env 42 execConfig.User = user 43 execConfig.WorkDir = workDir 44 execConfig.DetachKeys = &detachKeys 45 execConfig.PreserveFDs = preserveFDs 46 47 return ctr.Exec(execConfig, streams, resize) 48 } 49 50 // StartAttachCtr starts and (if required) attaches to a container 51 // if you change the signature of this function from os.File to io.Writer, it will trigger a downstream 52 // error. we may need to just lint disable this one. 53 func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { //nolint-interfacer 54 resize := make(chan remotecommand.TerminalSize) 55 56 haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) 57 58 // Check if we are attached to a terminal. If we are, generate resize 59 // events, and set the terminal to raw mode 60 if haveTerminal && ctr.Spec().Process.Terminal { 61 cancel, oldTermState, err := handleTerminalAttach(ctx, resize) 62 if err != nil { 63 return err 64 } 65 defer func() { 66 if err := restoreTerminal(oldTermState); err != nil { 67 logrus.Errorf("unable to restore terminal: %q", err) 68 } 69 }() 70 defer cancel() 71 } 72 73 streams := new(define.AttachStreams) 74 streams.OutputStream = stdout 75 streams.ErrorStream = stderr 76 streams.InputStream = bufio.NewReader(stdin) 77 streams.AttachOutput = true 78 streams.AttachError = true 79 streams.AttachInput = true 80 81 if stdout == nil { 82 logrus.Debugf("Not attaching to stdout") 83 streams.AttachOutput = false 84 } 85 if stderr == nil { 86 logrus.Debugf("Not attaching to stderr") 87 streams.AttachError = false 88 } 89 if stdin == nil { 90 logrus.Debugf("Not attaching to stdin") 91 streams.AttachInput = false 92 } 93 94 if !startContainer { 95 if sigProxy { 96 ProxySignals(ctr) 97 } 98 99 return ctr.Attach(streams, detachKeys, resize) 100 } 101 102 attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive) 103 if err != nil { 104 return err 105 } 106 107 if sigProxy { 108 ProxySignals(ctr) 109 } 110 111 if stdout == nil && stderr == nil { 112 fmt.Printf("%s\n", ctr.ID()) 113 } 114 115 err = <-attachChan 116 if err != nil { 117 return errors.Wrapf(err, "error attaching to container %s", ctr.ID()) 118 } 119 120 return nil 121 }