mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-18 08:26:45 +02:00
82 lines
1.7 KiB
Go
82 lines
1.7 KiB
Go
|
// 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")
|
||
|
}
|