2016-09-08 13:11:39 -04:00
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
gosignal "os/signal"
|
|
|
|
"runtime"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
2017-04-17 18:07:56 -04:00
|
|
|
"github.com/docker/cli/cli/command"
|
2016-09-08 13:11:39 -04:00
|
|
|
"github.com/docker/docker/api/types"
|
2017-05-08 13:51:30 -04:00
|
|
|
"github.com/docker/docker/client"
|
2016-09-08 13:11:39 -04:00
|
|
|
"github.com/docker/docker/pkg/signal"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
|
|
|
|
|
|
|
// resizeTtyTo resizes tty to specific height and width
|
2016-09-14 14:55:07 -04:00
|
|
|
func resizeTtyTo(ctx context.Context, client client.ContainerAPIClient, id string, height, width uint, isExec bool) {
|
2016-09-08 13:11:39 -04:00
|
|
|
if height == 0 && width == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
options := types.ResizeOptions{
|
|
|
|
Height: height,
|
|
|
|
Width: width,
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if isExec {
|
|
|
|
err = client.ContainerExecResize(ctx, id, options)
|
|
|
|
} else {
|
|
|
|
err = client.ContainerResize(ctx, id, options)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Debugf("Error resize: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MonitorTtySize updates the container tty size when the terminal tty changes size
|
|
|
|
func MonitorTtySize(ctx context.Context, cli *command.DockerCli, id string, isExec bool) error {
|
|
|
|
resizeTty := func() {
|
|
|
|
height, width := cli.Out().GetTtySize()
|
|
|
|
resizeTtyTo(ctx, cli.Client(), id, height, width, isExec)
|
|
|
|
}
|
|
|
|
|
|
|
|
resizeTty()
|
|
|
|
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
go func() {
|
|
|
|
prevH, prevW := cli.Out().GetTtySize()
|
|
|
|
for {
|
|
|
|
time.Sleep(time.Millisecond * 250)
|
|
|
|
h, w := cli.Out().GetTtySize()
|
|
|
|
|
|
|
|
if prevW != w || prevH != h {
|
|
|
|
resizeTty()
|
|
|
|
}
|
|
|
|
prevH = h
|
|
|
|
prevW = w
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
sigchan := make(chan os.Signal, 1)
|
|
|
|
gosignal.Notify(sigchan, signal.SIGWINCH)
|
|
|
|
go func() {
|
|
|
|
for range sigchan {
|
|
|
|
resizeTty()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ForwardAllSignals forwards signals to the container
|
|
|
|
func ForwardAllSignals(ctx context.Context, cli *command.DockerCli, cid string) chan os.Signal {
|
|
|
|
sigc := make(chan os.Signal, 128)
|
|
|
|
signal.CatchAll(sigc)
|
|
|
|
go func() {
|
|
|
|
for s := range sigc {
|
|
|
|
if s == signal.SIGCHLD || s == signal.SIGPIPE {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
var sig string
|
|
|
|
for sigStr, sigN := range signal.SignalMap {
|
|
|
|
if sigN == s {
|
|
|
|
sig = sigStr
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if sig == "" {
|
|
|
|
fmt.Fprintf(cli.Err(), "Unsupported signal: %v. Discarding.\n", s)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := cli.Client().ContainerKill(ctx, cid, sig); err != nil {
|
|
|
|
logrus.Debugf("Error sending signal: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return sigc
|
|
|
|
}
|