| ... | ... |
@@ -35,19 +35,6 @@ var ( |
| 35 | 35 |
func ParseCommands(args ...string) error {
|
| 36 | 36 |
cli := NewDockerCli("0.0.0.0", 4243)
|
| 37 | 37 |
|
| 38 |
- c := make(chan os.Signal, 1) |
|
| 39 |
- signal.Notify(c, syscall.SIGWINCH) |
|
| 40 |
- go func() {
|
|
| 41 |
- for sig := range c {
|
|
| 42 |
- if sig == syscall.SIGWINCH {
|
|
| 43 |
- _, _, err := cli.call("GET", "/auth", nil)
|
|
| 44 |
- if err != nil {
|
|
| 45 |
- utils.Debugf("Error resize: %s", err)
|
|
| 46 |
- } |
|
| 47 |
- } |
|
| 48 |
- } |
|
| 49 |
- }() |
|
| 50 |
- |
|
| 51 | 38 |
if len(args) > 0 {
|
| 52 | 39 |
methodName := "Cmd" + strings.ToUpper(args[0][:1]) + strings.ToLower(args[0][1:]) |
| 53 | 40 |
method, exists := reflect.TypeOf(cli).MethodByName(methodName) |
| ... | ... |
@@ -975,6 +962,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
| 975 | 975 |
v.Set("stderr", "1")
|
| 976 | 976 |
v.Set("stdin", "1")
|
| 977 | 977 |
|
| 978 |
+ cli.monitorTtySize(cmd.Arg(0)) |
|
| 978 | 979 |
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty); err != nil {
|
| 979 | 980 |
return err |
| 980 | 981 |
} |
| ... | ... |
@@ -1162,6 +1150,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 1162 | 1162 |
} |
| 1163 | 1163 |
|
| 1164 | 1164 |
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
|
| 1165 |
+ cli.monitorTtySize(out.Id) |
|
| 1165 | 1166 |
if err := cli.hijack("POST", "/containers/"+out.Id+"/attach?"+v.Encode(), config.Tty); err != nil {
|
| 1166 | 1167 |
return err |
| 1167 | 1168 |
} |
| ... | ... |
@@ -1295,6 +1284,33 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
|
| 1295 | 1295 |
|
| 1296 | 1296 |
} |
| 1297 | 1297 |
|
| 1298 |
+func (cli *DockerCli) resizeTty(id string) {
|
|
| 1299 |
+ ws, err := term.GetWinsize(os.Stdin.Fd()) |
|
| 1300 |
+ if err != nil {
|
|
| 1301 |
+ utils.Debugf("Error getting size: %s", err)
|
|
| 1302 |
+ } |
|
| 1303 |
+ v := url.Values{}
|
|
| 1304 |
+ v.Set("h", strconv.Itoa(int(ws.Height)))
|
|
| 1305 |
+ v.Set("w", strconv.Itoa(int(ws.Width)))
|
|
| 1306 |
+ if _, _, err := cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil); err != nil {
|
|
| 1307 |
+ utils.Debugf("Error resize: %s", err)
|
|
| 1308 |
+ } |
|
| 1309 |
+} |
|
| 1310 |
+ |
|
| 1311 |
+func (cli *DockerCli) monitorTtySize(id string) {
|
|
| 1312 |
+ cli.resizeTty(id) |
|
| 1313 |
+ |
|
| 1314 |
+ c := make(chan os.Signal, 1) |
|
| 1315 |
+ signal.Notify(c, syscall.SIGWINCH) |
|
| 1316 |
+ go func() {
|
|
| 1317 |
+ for sig := range c {
|
|
| 1318 |
+ if sig == syscall.SIGWINCH {
|
|
| 1319 |
+ cli.resizeTty(id) |
|
| 1320 |
+ } |
|
| 1321 |
+ } |
|
| 1322 |
+ }() |
|
| 1323 |
+} |
|
| 1324 |
+ |
|
| 1298 | 1325 |
func Subcmd(name, signature, description string) *flag.FlagSet {
|
| 1299 | 1326 |
flags := flag.NewFlagSet(name, flag.ContinueOnError) |
| 1300 | 1327 |
flags.Usage = func() {
|
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
"flag" |
| 6 | 6 |
"fmt" |
| 7 |
+ "github.com/dotcloud/docker/term" |
|
| 7 | 8 |
"github.com/dotcloud/docker/utils" |
| 8 | 9 |
"github.com/kr/pty" |
| 9 | 10 |
"io" |
| ... | ... |
@@ -755,7 +756,11 @@ func (container *Container) Wait() int {
|
| 755 | 755 |
} |
| 756 | 756 |
|
| 757 | 757 |
func (container *Container) Resize(h, w int) error {
|
| 758 |
- return fmt.Errorf("Resize not yet implemented")
|
|
| 758 |
+ pty, ok := container.ptyMaster.(*os.File) |
|
| 759 |
+ if !ok {
|
|
| 760 |
+ return fmt.Errorf("ptyMaster does not have Fd() method")
|
|
| 761 |
+ } |
|
| 762 |
+ return term.SetWinsize(pty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
|
| 759 | 763 |
} |
| 760 | 764 |
|
| 761 | 765 |
func (container *Container) ExportRw() (Archive, error) {
|
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package term |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "github.com/dotcloud/docker/utils" |
|
| 4 | 5 |
"os" |
| 5 | 6 |
"os/signal" |
| 6 | 7 |
"syscall" |
| ... | ... |
@@ -109,17 +110,35 @@ type State struct {
|
| 109 | 109 |
termios Termios |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 |
+type Winsize struct {
|
|
| 113 |
+ Width uint16 |
|
| 114 |
+ Height uint16 |
|
| 115 |
+ x uint16 |
|
| 116 |
+ y uint16 |
|
| 117 |
+} |
|
| 118 |
+ |
|
| 119 |
+func GetWinsize(fd uintptr) (*Winsize, error) {
|
|
| 120 |
+ ws := &Winsize{}
|
|
| 121 |
+ _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws))) |
|
| 122 |
+ return ws, err |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+func SetWinsize(fd uintptr, ws *Winsize) error {
|
|
| 126 |
+ _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) |
|
| 127 |
+ return err |
|
| 128 |
+} |
|
| 129 |
+ |
|
| 112 | 130 |
// IsTerminal returns true if the given file descriptor is a terminal. |
| 113 | 131 |
func IsTerminal(fd int) bool {
|
| 114 | 132 |
var termios Termios |
| 115 |
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios)), 0, 0, 0) |
|
| 133 |
+ _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) |
|
| 116 | 134 |
return err == 0 |
| 117 | 135 |
} |
| 118 | 136 |
|
| 119 | 137 |
// Restore restores the terminal connected to the given file descriptor to a |
| 120 | 138 |
// previous state. |
| 121 | 139 |
func Restore(fd int, state *State) error {
|
| 122 |
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) |
|
| 140 |
+ _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) |
|
| 123 | 141 |
return err |
| 124 | 142 |
} |
| 125 | 143 |
|