...
1
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
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
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
67
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