run.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // +build !windows
  2. package pty
  3. import (
  4. "os"
  5. "os/exec"
  6. "syscall"
  7. )
  8. // Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
  9. // and c.Stderr, calls c.Start, and returns the File of the tty's
  10. // corresponding pty.
  11. func Start(c *exec.Cmd) (pty *os.File, err error) {
  12. return StartWithSize(c, nil)
  13. }
  14. // StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
  15. // and c.Stderr, calls c.Start, and returns the File of the tty's
  16. // corresponding pty.
  17. //
  18. // This will resize the pty to the specified size before starting the command
  19. func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
  20. pty, tty, err := Open()
  21. if err != nil {
  22. return nil, err
  23. }
  24. defer tty.Close()
  25. if sz != nil {
  26. err = Setsize(pty, sz)
  27. if err != nil {
  28. pty.Close()
  29. return nil, err
  30. }
  31. }
  32. if c.Stdout == nil {
  33. c.Stdout = tty
  34. }
  35. if c.Stderr == nil {
  36. c.Stderr = tty
  37. }
  38. if c.Stdin == nil {
  39. c.Stdin = tty
  40. }
  41. if c.SysProcAttr == nil {
  42. c.SysProcAttr = &syscall.SysProcAttr{}
  43. }
  44. c.SysProcAttr.Setctty = true
  45. c.SysProcAttr.Setsid = true
  46. c.SysProcAttr.Ctty = int(tty.Fd())
  47. err = c.Start()
  48. if err != nil {
  49. pty.Close()
  50. return nil, err
  51. }
  52. return pty, err
  53. }