server_terminal.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ssh
  5. // A Terminal is capable of parsing and generating virtual terminal
  6. // data from an SSH client.
  7. type Terminal interface {
  8. ReadLine() (line string, err error)
  9. SetSize(x, y int)
  10. Write([]byte) (int, error)
  11. }
  12. // ServerTerminal contains the state for running a terminal that is capable of
  13. // reading lines of input.
  14. type ServerTerminal struct {
  15. Term Terminal
  16. Channel Channel
  17. }
  18. // parsePtyRequest parses the payload of the pty-req message and extracts the
  19. // dimensions of the terminal. See RFC 4254, section 6.2.
  20. func parsePtyRequest(s []byte) (width, height int, ok bool) {
  21. _, s, ok = parseString(s)
  22. if !ok {
  23. return
  24. }
  25. width32, s, ok := parseUint32(s)
  26. if !ok {
  27. return
  28. }
  29. height32, _, ok := parseUint32(s)
  30. width = int(width32)
  31. height = int(height32)
  32. if width < 1 {
  33. ok = false
  34. }
  35. if height < 1 {
  36. ok = false
  37. }
  38. return
  39. }
  40. func (ss *ServerTerminal) Write(buf []byte) (n int, err error) {
  41. return ss.Term.Write(buf)
  42. }
  43. // ReadLine returns a line of input from the terminal.
  44. func (ss *ServerTerminal) ReadLine() (line string, err error) {
  45. for {
  46. if line, err = ss.Term.ReadLine(); err == nil {
  47. return
  48. }
  49. req, ok := err.(ChannelRequest)
  50. if !ok {
  51. return
  52. }
  53. ok = false
  54. switch req.Request {
  55. case "pty-req":
  56. var width, height int
  57. width, height, ok = parsePtyRequest(req.Payload)
  58. ss.Term.SetSize(width, height)
  59. case "shell":
  60. ok = true
  61. if len(req.Payload) > 0 {
  62. // We don't accept any commands, only the default shell.
  63. ok = false
  64. }
  65. case "env":
  66. ok = true
  67. }
  68. if req.WantReply {
  69. ss.Channel.AckRequest(ok)
  70. }
  71. }
  72. panic("unreachable")
  73. }