Finish resize implementation client and server
This commit is contained in:
parent
deb9963e6e
commit
88ef309a94
3 changed files with 56 additions and 16 deletions
42
commands.go
42
commands.go
|
@ -35,19 +35,6 @@ var (
|
|||
func ParseCommands(args ...string) error {
|
||||
cli := NewDockerCli("0.0.0.0", 4243)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGWINCH)
|
||||
go func() {
|
||||
for sig := range c {
|
||||
if sig == syscall.SIGWINCH {
|
||||
_, _, err := cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
utils.Debugf("Error resize: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if len(args) > 0 {
|
||||
methodName := "Cmd" + strings.ToUpper(args[0][:1]) + strings.ToLower(args[0][1:])
|
||||
method, exists := reflect.TypeOf(cli).MethodByName(methodName)
|
||||
|
@ -975,6 +962,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
|||
v.Set("stderr", "1")
|
||||
v.Set("stdin", "1")
|
||||
|
||||
cli.monitorTtySize(cmd.Arg(0))
|
||||
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1162,6 +1150,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||
}
|
||||
|
||||
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
|
||||
cli.monitorTtySize(out.Id)
|
||||
if err := cli.hijack("POST", "/containers/"+out.Id+"/attach?"+v.Encode(), config.Tty); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1295,6 +1284,33 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
|
|||
|
||||
}
|
||||
|
||||
func (cli *DockerCli) resizeTty(id string) {
|
||||
ws, err := term.GetWinsize(os.Stdin.Fd())
|
||||
if err != nil {
|
||||
utils.Debugf("Error getting size: %s", err)
|
||||
}
|
||||
v := url.Values{}
|
||||
v.Set("h", strconv.Itoa(int(ws.Height)))
|
||||
v.Set("w", strconv.Itoa(int(ws.Width)))
|
||||
if _, _, err := cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil); err != nil {
|
||||
utils.Debugf("Error resize: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *DockerCli) monitorTtySize(id string) {
|
||||
cli.resizeTty(id)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGWINCH)
|
||||
go func() {
|
||||
for sig := range c {
|
||||
if sig == syscall.SIGWINCH {
|
||||
cli.resizeTty(id)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func Subcmd(name, signature, description string) *flag.FlagSet {
|
||||
flags := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||
flags.Usage = func() {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/term"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/kr/pty"
|
||||
"io"
|
||||
|
@ -755,7 +756,11 @@ func (container *Container) Wait() int {
|
|||
}
|
||||
|
||||
func (container *Container) Resize(h, w int) error {
|
||||
return fmt.Errorf("Resize not yet implemented")
|
||||
pty, ok := container.ptyMaster.(*os.File)
|
||||
if !ok {
|
||||
return fmt.Errorf("ptyMaster does not have Fd() method")
|
||||
}
|
||||
return term.SetWinsize(pty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
||||
}
|
||||
|
||||
func (container *Container) ExportRw() (Archive, error) {
|
||||
|
|
23
term/term.go
23
term/term.go
|
@ -1,6 +1,7 @@
|
|||
package term
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
@ -109,17 +110,35 @@ type State struct {
|
|||
termios Termios
|
||||
}
|
||||
|
||||
type Winsize struct {
|
||||
Width uint16
|
||||
Height uint16
|
||||
x uint16
|
||||
y uint16
|
||||
}
|
||||
|
||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
ws := &Winsize{}
|
||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
|
||||
return ws, err
|
||||
}
|
||||
|
||||
func SetWinsize(fd uintptr, ws *Winsize) error {
|
||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
|
||||
return err
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd int) bool {
|
||||
var termios Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios)))
|
||||
return err == 0
|
||||
}
|
||||
|
||||
// Restore restores the terminal connected to the given file descriptor to a
|
||||
// previous state.
|
||||
func Restore(fd int, state *State) error {
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
|
||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios)))
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue