func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli { var ( isTerminal = false terminalFd uintptr ) if in != nil { if file, ok := in.(*os.File); ok { terminalFd = file.Fd() isTerminal = term.IsTerminal(terminalFd) } } if err == nil { err = out } return &DockerCli{ proto: proto, addr: addr, in: in, out: out, err: err, isTerminal: isTerminal, terminalFd: terminalFd, tlsConfig: tlsConfig, } }
func (c *DockerClient) hijack(method, path string, setRawTerminal bool, in io.Reader, errStream io.Writer, out io.Writer) error { req, err := http.NewRequest(method, c.getURL(path), nil) if err != nil { return err } req.Header.Set("Content-Type", "plain/text") protocol := c.endpointURL.Scheme address := c.endpointURL.Path if protocol != "unix" { protocol = "tcp" address = c.endpointURL.Host } dial, err := net.Dial(protocol, address) if err != nil { return err } clientconn := httputil.NewClientConn(dial, nil) clientconn.Do(req) defer clientconn.Close() rwc, br := clientconn.Hijack() defer rwc.Close() errStdout := make(chan error, 1) go func() { var err error if setRawTerminal { _, err = io.Copy(out, br) } else { _, err = utils.StdCopy(out, errStream, br) } errStdout <- err }() if inFile, ok := in.(*os.File); ok && setRawTerminal && term.IsTerminal(inFile.Fd()) && os.Getenv("NORAW") == "" { oldState, err := term.SetRawTerminal(inFile.Fd()) if err != nil { return err } defer term.RestoreTerminal(inFile.Fd(), oldState) } go func() { if in != nil { io.Copy(rwc, in) } if err := rwc.(interface { CloseWrite() error }).CloseWrite(); err != nil && errStream != nil { fmt.Fprintf(errStream, "Couldn't send EOF: %s\n", err) } }() if err := <-errStdout; err != nil { return err } return nil }
func CmdPrompt(args []string, stdout, stderr io.Writer, in beam.Receiver, out beam.Sender) { if len(args) < 2 { fmt.Fprintf(stderr, "usage: %s PROMPT...\n", args[0]) return } if !term.IsTerminal(0) { fmt.Fprintf(stderr, "can't prompt: no tty available...\n") return } fmt.Printf("%s: ", strings.Join(args[1:], " ")) oldState, _ := term.SaveState(0) term.DisableEcho(0, oldState) line, _, err := bufio.NewReader(os.Stdin).ReadLine() if err != nil { fmt.Fprintln(stderr, err.Error()) return } val := string(line) fmt.Printf("\n") term.RestoreTerminal(0, oldState) out.Send(data.Empty().Set("fromcmd", args...).Set("value", val).Bytes(), nil) }
func (c *Client) stream(method, path string, in io.Reader, out io.Writer, headers http.Header) error { if (method == "POST" || method == "PUT") && in == nil { in = bytes.NewReader(nil) } // setup the request req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), in) if err != nil { return err } // set default headers req.Header = headers req.Header.Set("User-Agent", "Docker-Client/0.6.4") req.Header.Set("Content-Type", "plain/text") // dial the host server req.Host = c.addr dial, err := net.Dial(c.proto, c.addr) if err != nil { return err } // make the request conn := httputil.NewClientConn(dial, nil) resp, err := conn.Do(req) defer conn.Close() if err != nil { return err } // make sure we defer close the body defer resp.Body.Close() // Check for an http error status (ie not 200 StatusOK) switch resp.StatusCode { case 404: return ErrNotFound case 403: return ErrForbidden case 401: return ErrNotAuthorized case 400: return ErrBadRequest } // If no output we exit now with no errors if out == nil { return nil } // copy the output stream to the writer if resp.Header.Get("Content-Type") == "application/json" { var terminalFd = os.Stdin.Fd() var isTerminal = term.IsTerminal(terminalFd) // it may not make sense to put this code here, but it works for // us at the moment, and I don't feel like refactoring return utils.DisplayJSONMessagesStream(resp.Body, out, terminalFd, isTerminal) } // otherwise plain text if _, err := io.Copy(out, resp.Body); err != nil { return err } return nil }
func main() { fd3 := os.NewFile(3, "beam-introspect") if introsp, err := beam.FileConn(fd3); err == nil { introspect = introsp Logf("introspection enabled\n") } else { Logf("introspection disabled\n") } fd3.Close() flag.BoolVar(&flX, "x", false, "print commands as they are being executed") flag.Parse() if flag.NArg() == 0 { if term.IsTerminal(0) { // No arguments, stdin is terminal --> interactive mode input := bufio.NewScanner(os.Stdin) for { fmt.Printf("[%d] beamsh> ", os.Getpid()) if !input.Scan() { break } line := input.Text() if len(line) != 0 { cmd, err := dockerscript.Parse(strings.NewReader(line)) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) continue } if err := executeRootScript(cmd); err != nil { Fatal(err) } } if err := input.Err(); err == io.EOF { break } else if err != nil { Fatal(err) } } } else { // No arguments, stdin not terminal --> batch mode script, err := dockerscript.Parse(os.Stdin) if err != nil { Fatal("parse error: %v\n", err) } if err := executeRootScript(script); err != nil { Fatal(err) } } } else { // 1+ arguments: parse them as script files for _, scriptpath := range flag.Args() { f, err := os.Open(scriptpath) if err != nil { Fatal(err) } script, err := dockerscript.Parse(f) if err != nil { Fatal("parse error: %v\n", err) } if err := executeRootScript(script); err != nil { Fatal(err) } } } }
func init() { if term.IsTerminal(1) { Colorize = true } }