|
@@ -10,10 +10,8 @@ import (
|
|
"github.com/dotcloud/docker/graphdriver"
|
|
"github.com/dotcloud/docker/graphdriver"
|
|
"github.com/dotcloud/docker/links"
|
|
"github.com/dotcloud/docker/links"
|
|
"github.com/dotcloud/docker/nat"
|
|
"github.com/dotcloud/docker/nat"
|
|
- "github.com/dotcloud/docker/pkg/term"
|
|
|
|
"github.com/dotcloud/docker/runconfig"
|
|
"github.com/dotcloud/docker/runconfig"
|
|
"github.com/dotcloud/docker/utils"
|
|
"github.com/dotcloud/docker/utils"
|
|
- "github.com/kr/pty"
|
|
|
|
"io"
|
|
"io"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"log"
|
|
"log"
|
|
@@ -61,7 +59,6 @@ type Container struct {
|
|
stderr *utils.WriteBroadcaster
|
|
stderr *utils.WriteBroadcaster
|
|
stdin io.ReadCloser
|
|
stdin io.ReadCloser
|
|
stdinPipe io.WriteCloser
|
|
stdinPipe io.WriteCloser
|
|
- ptyMaster io.Closer
|
|
|
|
|
|
|
|
runtime *Runtime
|
|
runtime *Runtime
|
|
|
|
|
|
@@ -213,56 +210,6 @@ func (container *Container) generateEnvConfig(env []string) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (container *Container) setupPty() error {
|
|
|
|
- ptyMaster, ptySlave, err := pty.Open()
|
|
|
|
- if err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- container.ptyMaster = ptyMaster
|
|
|
|
- container.command.Stdout = ptySlave
|
|
|
|
- container.command.Stderr = ptySlave
|
|
|
|
- container.command.Console = ptySlave.Name()
|
|
|
|
-
|
|
|
|
- // Copy the PTYs to our broadcasters
|
|
|
|
- go func() {
|
|
|
|
- defer container.stdout.CloseWriters()
|
|
|
|
- utils.Debugf("startPty: begin of stdout pipe")
|
|
|
|
- io.Copy(container.stdout, ptyMaster)
|
|
|
|
- utils.Debugf("startPty: end of stdout pipe")
|
|
|
|
- }()
|
|
|
|
-
|
|
|
|
- // stdin
|
|
|
|
- if container.Config.OpenStdin {
|
|
|
|
- container.command.Stdin = ptySlave
|
|
|
|
- container.command.SysProcAttr.Setctty = true
|
|
|
|
- go func() {
|
|
|
|
- defer container.stdin.Close()
|
|
|
|
- utils.Debugf("startPty: begin of stdin pipe")
|
|
|
|
- io.Copy(ptyMaster, container.stdin)
|
|
|
|
- utils.Debugf("startPty: end of stdin pipe")
|
|
|
|
- }()
|
|
|
|
- }
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (container *Container) setupStd() error {
|
|
|
|
- container.command.Stdout = container.stdout
|
|
|
|
- container.command.Stderr = container.stderr
|
|
|
|
- if container.Config.OpenStdin {
|
|
|
|
- stdin, err := container.command.StdinPipe()
|
|
|
|
- if err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- go func() {
|
|
|
|
- defer stdin.Close()
|
|
|
|
- utils.Debugf("start: begin of stdin pipe")
|
|
|
|
- io.Copy(stdin, container.stdin)
|
|
|
|
- utils.Debugf("start: end of stdin pipe")
|
|
|
|
- }()
|
|
|
|
- }
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
|
|
func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
|
|
var cStdout, cStderr io.ReadCloser
|
|
var cStdout, cStderr io.ReadCloser
|
|
|
|
|
|
@@ -593,17 +540,6 @@ func (container *Container) Start() (err error) {
|
|
}
|
|
}
|
|
container.waitLock = make(chan struct{})
|
|
container.waitLock = make(chan struct{})
|
|
|
|
|
|
- // Setuping pipes and/or Pty
|
|
|
|
- var setup func() error
|
|
|
|
- if container.Config.Tty {
|
|
|
|
- setup = container.setupPty
|
|
|
|
- } else {
|
|
|
|
- setup = container.setupStd
|
|
|
|
- }
|
|
|
|
- if err := setup(); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
callbackLock := make(chan struct{})
|
|
callbackLock := make(chan struct{})
|
|
callback := func(command *execdriver.Command) {
|
|
callback := func(command *execdriver.Command) {
|
|
container.State.SetRunning(command.Pid())
|
|
container.State.SetRunning(command.Pid())
|
|
@@ -843,7 +779,8 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
|
|
populateCommand(container)
|
|
populateCommand(container)
|
|
err = container.runtime.RestoreCommand(container)
|
|
err = container.runtime.RestoreCommand(container)
|
|
} else {
|
|
} else {
|
|
- exitCode, err = container.runtime.Run(container, callback)
|
|
|
|
|
|
+ pipes := execdriver.NewPipes(container.stdin, container.stdout, container.stderr, container.Config.OpenStdin)
|
|
|
|
+ exitCode, err = container.runtime.Run(container, pipes, callback)
|
|
}
|
|
}
|
|
|
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -887,7 +824,6 @@ func (container *Container) cleanup() {
|
|
link.Disable()
|
|
link.Disable()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
if container.Config.OpenStdin {
|
|
if container.Config.OpenStdin {
|
|
if err := container.stdin.Close(); err != nil {
|
|
if err := container.stdin.Close(); err != nil {
|
|
utils.Errorf("%s: Error close stdin: %s", container.ID, err)
|
|
utils.Errorf("%s: Error close stdin: %s", container.ID, err)
|
|
@@ -899,10 +835,9 @@ func (container *Container) cleanup() {
|
|
if err := container.stderr.CloseWriters(); err != nil {
|
|
if err := container.stderr.CloseWriters(); err != nil {
|
|
utils.Errorf("%s: Error close stderr: %s", container.ID, err)
|
|
utils.Errorf("%s: Error close stderr: %s", container.ID, err)
|
|
}
|
|
}
|
|
-
|
|
|
|
- if container.ptyMaster != nil {
|
|
|
|
- if err := container.ptyMaster.Close(); err != nil {
|
|
|
|
- utils.Errorf("%s: Error closing Pty master: %s", container.ID, err)
|
|
|
|
|
|
+ if container.command.Terminal != nil {
|
|
|
|
+ if err := container.command.Terminal.Close(); err != nil {
|
|
|
|
+ utils.Errorf("%s: Error closing terminal: %s", container.ID, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -994,11 +929,7 @@ func (container *Container) Wait() int {
|
|
}
|
|
}
|
|
|
|
|
|
func (container *Container) Resize(h, w int) error {
|
|
func (container *Container) Resize(h, w int) error {
|
|
- 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)})
|
|
|
|
|
|
+ return container.command.Terminal.Resize(h, w)
|
|
}
|
|
}
|
|
|
|
|
|
func (container *Container) ExportRw() (archive.Archive, error) {
|
|
func (container *Container) ExportRw() (archive.Archive, error) {
|
|
@@ -1202,11 +1133,9 @@ func (container *Container) Exposes(p nat.Port) bool {
|
|
}
|
|
}
|
|
|
|
|
|
func (container *Container) GetPtyMaster() (*os.File, error) {
|
|
func (container *Container) GetPtyMaster() (*os.File, error) {
|
|
- if container.ptyMaster == nil {
|
|
|
|
|
|
+ ttyConsole, ok := container.command.Terminal.(execdriver.TtyTerminal)
|
|
|
|
+ if !ok {
|
|
return nil, ErrNoTTY
|
|
return nil, ErrNoTTY
|
|
}
|
|
}
|
|
- if pty, ok := container.ptyMaster.(*os.File); ok {
|
|
|
|
- return pty, nil
|
|
|
|
- }
|
|
|
|
- return nil, ErrNotATTY
|
|
|
|
|
|
+ return ttyConsole.Master(), nil
|
|
}
|
|
}
|