func (srv *Server) CmdAttach(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error { cmd := rcli.Subcmd(stdout, "attach", "CONTAINER", "Attach to a running container") if err := cmd.Parse(args); err != nil { return nil } if cmd.NArg() != 1 { cmd.Usage() return nil } name := cmd.Arg(0) container := srv.runtime.Get(name) if container == nil { return fmt.Errorf("No such container: %s", name) } if container.State.Ghost { return fmt.Errorf("Impossible to attach to a ghost container") } if container.Config.Tty { stdout.SetOptionRawTerminal() } // Flush the options to make sure the client sets the raw mode stdout.Flush() return <-container.Attach(stdin, nil, stdout, stdout) }
func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error { config, err := ParseRun(args, stdout) if err != nil { return err } if config.Image == "" { fmt.Fprintln(stdout, "Error: Image not specified") return fmt.Errorf("Image not specified") } if len(config.Cmd) == 0 { fmt.Fprintln(stdout, "Error: Command not specified") return fmt.Errorf("Command not specified") } if config.Tty { stdout.SetOptionRawTerminal() } // Flush the options to make sure the client sets the raw mode // or tell the client there is no options stdout.Flush() // Create new container container, err := srv.runtime.Create(config) if err != nil { // If container not found, try to pull it if srv.runtime.graph.IsNotExist(err) { fmt.Fprintf(stdout, "Image %s not found, trying to pull it from registry.\r\n", config.Image) if err = srv.CmdPull(stdin, stdout, config.Image); err != nil { return err } if container, err = srv.runtime.Create(config); err != nil { return err } } else { return err } } var ( cStdin io.ReadCloser cStdout, cStderr io.Writer ) if config.AttachStdin { r, w := io.Pipe() go func() { defer w.Close() defer Debugf("Closing buffered stdin pipe") io.Copy(w, stdin) }() cStdin = r } if config.AttachStdout { cStdout = stdout } if config.AttachStderr { cStderr = stdout // FIXME: rcli can't differentiate stdout from stderr } attachErr := container.Attach(cStdin, stdin, cStdout, cStderr) Debugf("Starting\n") if err := container.Start(); err != nil { return err } if cStdout == nil && cStderr == nil { fmt.Fprintln(stdout, container.ShortId()) } Debugf("Waiting for attach to return\n") <-attachErr container.Wait() // Expecting I/O pipe error, discarding return nil }
// 'docker login': login / register a user to registry service. func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error { // Read a line on raw terminal with support for simple backspace // sequences and echo. // // This function is necessary because the login command must be done in a // raw terminal for two reasons: // - we have to read a password (without echoing it); // - the rcli "protocol" only supports cannonical and raw modes and you // can't tune it once the command as been started. var readStringOnRawTerminal = func(stdin io.Reader, stdout io.Writer, echo bool) string { char := make([]byte, 1) buffer := make([]byte, 64) var i = 0 for i < len(buffer) { n, err := stdin.Read(char) if n > 0 { if char[0] == '\r' || char[0] == '\n' { stdout.Write([]byte{'\r', '\n'}) break } else if char[0] == 127 || char[0] == '\b' { if i > 0 { if echo { stdout.Write([]byte{'\b', ' ', '\b'}) } i-- } } else if !unicode.IsSpace(rune(char[0])) && !unicode.IsControl(rune(char[0])) { if echo { stdout.Write(char) } buffer[i] = char[0] i++ } } if err != nil { if err != io.EOF { fmt.Fprintf(stdout, "Read error: %v\r\n", err) } break } } return string(buffer[:i]) } var readAndEchoString = func(stdin io.Reader, stdout io.Writer) string { return readStringOnRawTerminal(stdin, stdout, true) } var readString = func(stdin io.Reader, stdout io.Writer) string { return readStringOnRawTerminal(stdin, stdout, false) } stdout.SetOptionRawTerminal() cmd := rcli.Subcmd(stdout, "login", "", "Register or Login to the docker registry server") if err := cmd.Parse(args); err != nil { return nil } var username string var password string var email string fmt.Fprint(stdout, "Username (", srv.runtime.authConfig.Username, "): ") username = readAndEchoString(stdin, stdout) if username == "" { username = srv.runtime.authConfig.Username } if username != srv.runtime.authConfig.Username { fmt.Fprint(stdout, "Password: "******"" { return fmt.Errorf("Error : Password Required") } fmt.Fprint(stdout, "Email (", srv.runtime.authConfig.Email, "): ") email = readAndEchoString(stdin, stdout) if email == "" { email = srv.runtime.authConfig.Email } } else { password = srv.runtime.authConfig.Password email = srv.runtime.authConfig.Email } newAuthConfig := auth.NewAuthConfig(username, password, email, srv.runtime.root) status, err := auth.Login(newAuthConfig) if err != nil { fmt.Fprintf(stdout, "Error: %s\r\n", err) } else { srv.runtime.authConfig = newAuthConfig } if status != "" { fmt.Fprint(stdout, status) } return nil }