...

Source file src/github.com/Microsoft/hcsshim/cmd/shimdiag/exec.go

Documentation: github.com/Microsoft/hcsshim/cmd/shimdiag

     1  //go:build windows
     2  
     3  package main
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"io"
     9  	"os"
    10  	"os/signal"
    11  	"syscall"
    12  
    13  	"github.com/Microsoft/hcsshim/internal/appargs"
    14  	"github.com/Microsoft/hcsshim/internal/cmd"
    15  	"github.com/Microsoft/hcsshim/internal/shimdiag"
    16  	"github.com/containerd/console"
    17  	"github.com/urfave/cli"
    18  )
    19  
    20  type rawConReader struct {
    21  	f *os.File
    22  }
    23  
    24  func (r rawConReader) Read(b []byte) (int, error) {
    25  	n, err := syscall.Read(syscall.Handle(r.f.Fd()), b)
    26  	if n == 0 && len(b) != 0 && err == nil {
    27  		// A zero-byte read on a console indicates that the user wrote Ctrl-Z.
    28  		b[0] = 26
    29  		return 1, nil
    30  	}
    31  	return n, err
    32  }
    33  
    34  var execTty bool
    35  var execCommand = cli.Command{
    36  	Name:      "exec",
    37  	Usage:     "Executes a command in a shim's hosting utility VM",
    38  	ArgsUsage: "[flags] <shim name> <command> [args...]",
    39  	Flags: []cli.Flag{
    40  		cli.BoolFlag{
    41  			Name:        "tty,t",
    42  			Usage:       "run with a terminal",
    43  			Destination: &execTty},
    44  	},
    45  	SkipArgReorder: true,
    46  	Before:         appargs.Validate(appargs.String, appargs.String, appargs.Rest(appargs.String)),
    47  	Action: func(clictx *cli.Context) error {
    48  		args := clictx.Args()
    49  		shim, err := shimdiag.GetShim(args[0])
    50  		if err != nil {
    51  			return err
    52  		}
    53  
    54  		var osStdin io.Reader = os.Stdin
    55  		if execTty {
    56  			// Enable raw mode on the client's console.
    57  			con, err := console.ConsoleFromFile(os.Stdin)
    58  			if err == nil {
    59  				err = con.SetRaw()
    60  				if err != nil {
    61  					return err
    62  				}
    63  				defer func() {
    64  					_ = con.Reset()
    65  				}()
    66  				// Console reads return EOF whenever the user presses Ctrl-Z.
    67  				// Wrap the reads to translate these EOFs back.
    68  				osStdin = rawConReader{os.Stdin}
    69  			}
    70  		}
    71  
    72  		stdin, err := cmd.CreatePipeAndListen(osStdin, true)
    73  		if err != nil {
    74  			return err
    75  		}
    76  		stdout, err := cmd.CreatePipeAndListen(os.Stdout, false)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		var stderr string
    81  		if !execTty {
    82  			stderr, err = cmd.CreatePipeAndListen(os.Stderr, false)
    83  			if err != nil {
    84  				return err
    85  			}
    86  		}
    87  		ch := make(chan os.Signal, 1)
    88  		signal.Notify(ch, os.Interrupt)
    89  		ctx, cancel := context.WithCancel(context.Background())
    90  		go func() {
    91  			<-ch
    92  			cancel()
    93  		}()
    94  		svc := shimdiag.NewShimDiagClient(shim)
    95  		resp, err := svc.DiagExecInHost(ctx, &shimdiag.ExecProcessRequest{
    96  			Args:     args[1:],
    97  			Stdin:    stdin,
    98  			Stdout:   stdout,
    99  			Stderr:   stderr,
   100  			Terminal: execTty,
   101  		})
   102  		if err != nil {
   103  			return err
   104  		}
   105  		return cli.NewExitError(errors.New(""), int(resp.ExitCode))
   106  	},
   107  }
   108  

View as plain text