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