util.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // +build !windows,!solaris
  2. package pty
  3. import (
  4. "os"
  5. "syscall"
  6. "unsafe"
  7. )
  8. // InheritSize applies the terminal size of pty to tty. This should be run
  9. // in a signal handler for syscall.SIGWINCH to automatically resize the tty when
  10. // the pty receives a window size change notification.
  11. func InheritSize(pty, tty *os.File) error {
  12. size, err := GetsizeFull(pty)
  13. if err != nil {
  14. return err
  15. }
  16. err = Setsize(tty, size)
  17. if err != nil {
  18. return err
  19. }
  20. return nil
  21. }
  22. // Setsize resizes t to s.
  23. func Setsize(t *os.File, ws *Winsize) error {
  24. return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ)
  25. }
  26. // GetsizeFull returns the full terminal size description.
  27. func GetsizeFull(t *os.File) (size *Winsize, err error) {
  28. var ws Winsize
  29. err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ)
  30. return &ws, err
  31. }
  32. // Getsize returns the number of rows (lines) and cols (positions
  33. // in each line) in terminal t.
  34. func Getsize(t *os.File) (rows, cols int, err error) {
  35. ws, err := GetsizeFull(t)
  36. return int(ws.Rows), int(ws.Cols), err
  37. }
  38. // Winsize describes the terminal size.
  39. type Winsize struct {
  40. Rows uint16 // ws_row: Number of rows (in cells)
  41. Cols uint16 // ws_col: Number of columns (in cells)
  42. X uint16 // ws_xpixel: Width in pixels
  43. Y uint16 // ws_ypixel: Height in pixels
  44. }
  45. func windowRectCall(ws *Winsize, fd, a2 uintptr) error {
  46. _, _, errno := syscall.Syscall(
  47. syscall.SYS_IOCTL,
  48. fd,
  49. a2,
  50. uintptr(unsafe.Pointer(ws)),
  51. )
  52. if errno != 0 {
  53. return syscall.Errno(errno)
  54. }
  55. return nil
  56. }