// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssh // A Terminal is capable of parsing and generating virtual terminal // data from an SSH client. type Terminal interface { ReadLine() (line string, err error) SetSize(x, y int) Write([]byte) (int, error) } // ServerTerminal contains the state for running a terminal that is capable of // reading lines of input. type ServerTerminal struct { Term Terminal Channel Channel } // parsePtyRequest parses the payload of the pty-req message and extracts the // dimensions of the terminal. See RFC 4254, section 6.2. func parsePtyRequest(s []byte) (width, height int, ok bool) { _, s, ok = parseString(s) if !ok { return } width32, s, ok := parseUint32(s) if !ok { return } height32, _, ok := parseUint32(s) width = int(width32) height = int(height32) if width < 1 { ok = false } if height < 1 { ok = false } return } func (ss *ServerTerminal) Write(buf []byte) (n int, err error) { return ss.Term.Write(buf) } // ReadLine returns a line of input from the terminal. func (ss *ServerTerminal) ReadLine() (line string, err error) { for { if line, err = ss.Term.ReadLine(); err == nil { return } req, ok := err.(ChannelRequest) if !ok { return } ok = false switch req.Request { case "pty-req": var width, height int width, height, ok = parsePtyRequest(req.Payload) ss.Term.SetSize(width, height) case "shell": ok = true if len(req.Payload) > 0 { // We don't accept any commands, only the default shell. ok = false } case "env": ok = true } if req.WantReply { ss.Channel.AckRequest(ok) } } panic("unreachable") }