github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/domain/infra/abi/terminal/terminal_linux.go (about)

     1  package terminal
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"fmt"
     7  	"os"
     8  
     9  	"github.com/containers/podman/v2/libpod"
    10  	"github.com/containers/podman/v2/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, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (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 && execConfig.Terminal {
    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  	return ctr.Exec(execConfig, streams, resize)
    38  }
    39  
    40  // StartAttachCtr starts and (if required) attaches to a container
    41  // if you change the signature of this function from os.File to io.Writer, it will trigger a downstream
    42  // error. we may need to just lint disable this one.
    43  func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { //nolint-interfacer
    44  	resize := make(chan remotecommand.TerminalSize)
    45  
    46  	haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
    47  
    48  	// Check if we are attached to a terminal. If we are, generate resize
    49  	// events, and set the terminal to raw mode
    50  	if haveTerminal && ctr.Spec().Process.Terminal {
    51  		cancel, oldTermState, err := handleTerminalAttach(ctx, resize)
    52  		if err != nil {
    53  			return err
    54  		}
    55  		defer func() {
    56  			if err := restoreTerminal(oldTermState); err != nil {
    57  				logrus.Errorf("unable to restore terminal: %q", err)
    58  			}
    59  		}()
    60  		defer cancel()
    61  	}
    62  
    63  	streams := new(define.AttachStreams)
    64  	streams.OutputStream = stdout
    65  	streams.ErrorStream = stderr
    66  	streams.InputStream = bufio.NewReader(stdin)
    67  	streams.AttachOutput = true
    68  	streams.AttachError = true
    69  	streams.AttachInput = true
    70  
    71  	if stdout == nil {
    72  		logrus.Debugf("Not attaching to stdout")
    73  		streams.AttachOutput = false
    74  	}
    75  	if stderr == nil {
    76  		logrus.Debugf("Not attaching to stderr")
    77  		streams.AttachError = false
    78  	}
    79  	if stdin == nil {
    80  		logrus.Debugf("Not attaching to stdin")
    81  		streams.AttachInput = false
    82  	}
    83  
    84  	if !startContainer {
    85  		if sigProxy {
    86  			ProxySignals(ctr)
    87  		}
    88  
    89  		return ctr.Attach(streams, detachKeys, resize)
    90  	}
    91  
    92  	attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	if sigProxy {
    98  		ProxySignals(ctr)
    99  	}
   100  
   101  	if stdout == nil && stderr == nil {
   102  		fmt.Printf("%s\n", ctr.ID())
   103  	}
   104  
   105  	err = <-attachChan
   106  	if err != nil {
   107  		return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
   108  	}
   109  
   110  	return nil
   111  }