github.com/kunnos/engine@v1.13.1/cli/command/container/tty.go (about) 1 package container 2 3 import ( 4 "fmt" 5 "os" 6 gosignal "os/signal" 7 "runtime" 8 "time" 9 10 "github.com/sirupsen/logrus" 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/cli/command" 13 "github.com/docker/docker/client" 14 "github.com/docker/docker/pkg/signal" 15 "golang.org/x/net/context" 16 ) 17 18 // resizeTtyTo resizes tty to specific height and width 19 func resizeTtyTo(ctx context.Context, client client.ContainerAPIClient, id string, height, width uint, isExec bool) { 20 if height == 0 && width == 0 { 21 return 22 } 23 24 options := types.ResizeOptions{ 25 Height: height, 26 Width: width, 27 } 28 29 var err error 30 if isExec { 31 err = client.ContainerExecResize(ctx, id, options) 32 } else { 33 err = client.ContainerResize(ctx, id, options) 34 } 35 36 if err != nil { 37 logrus.Debugf("Error resize: %s", err) 38 } 39 } 40 41 // MonitorTtySize updates the container tty size when the terminal tty changes size 42 func MonitorTtySize(ctx context.Context, cli *command.DockerCli, id string, isExec bool) error { 43 resizeTty := func() { 44 height, width := cli.Out().GetTtySize() 45 resizeTtyTo(ctx, cli.Client(), id, height, width, isExec) 46 } 47 48 resizeTty() 49 50 if runtime.GOOS == "windows" { 51 go func() { 52 prevH, prevW := cli.Out().GetTtySize() 53 for { 54 time.Sleep(time.Millisecond * 250) 55 h, w := cli.Out().GetTtySize() 56 57 if prevW != w || prevH != h { 58 resizeTty() 59 } 60 prevH = h 61 prevW = w 62 } 63 }() 64 } else { 65 sigchan := make(chan os.Signal, 1) 66 gosignal.Notify(sigchan, signal.SIGWINCH) 67 go func() { 68 for range sigchan { 69 resizeTty() 70 } 71 }() 72 } 73 return nil 74 } 75 76 // ForwardAllSignals forwards signals to the container 77 func ForwardAllSignals(ctx context.Context, cli *command.DockerCli, cid string) chan os.Signal { 78 sigc := make(chan os.Signal, 128) 79 signal.CatchAll(sigc) 80 go func() { 81 for s := range sigc { 82 if s == signal.SIGCHLD || s == signal.SIGPIPE { 83 continue 84 } 85 var sig string 86 for sigStr, sigN := range signal.SignalMap { 87 if sigN == s { 88 sig = sigStr 89 break 90 } 91 } 92 if sig == "" { 93 fmt.Fprintf(cli.Err(), "Unsupported signal: %v. Discarding.\n", s) 94 continue 95 } 96 97 if err := cli.Client().ContainerKill(ctx, cid, sig); err != nil { 98 logrus.Debugf("Error sending signal: %s", err) 99 } 100 } 101 }() 102 return sigc 103 }