pty_freebsd.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //go:build freebsd
  2. // +build freebsd
  3. package pty
  4. import (
  5. "errors"
  6. "os"
  7. "syscall"
  8. "unsafe"
  9. )
  10. func posixOpenpt(oflag int) (fd int, err error) {
  11. r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0)
  12. fd = int(r0)
  13. if e1 != 0 {
  14. err = e1
  15. }
  16. return fd, err
  17. }
  18. func open() (pty, tty *os.File, err error) {
  19. fd, err := posixOpenpt(syscall.O_RDWR | syscall.O_CLOEXEC)
  20. if err != nil {
  21. return nil, nil, err
  22. }
  23. p := os.NewFile(uintptr(fd), "/dev/pts")
  24. // In case of error after this point, make sure we close the pts fd.
  25. defer func() {
  26. if err != nil {
  27. _ = p.Close() // Best effort.
  28. }
  29. }()
  30. sname, err := ptsname(p)
  31. if err != nil {
  32. return nil, nil, err
  33. }
  34. t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0)
  35. if err != nil {
  36. return nil, nil, err
  37. }
  38. return p, t, nil
  39. }
  40. func isptmaster(fd uintptr) (bool, error) {
  41. err := ioctl(fd, syscall.TIOCPTMASTER, 0)
  42. return err == nil, err
  43. }
  44. var (
  45. emptyFiodgnameArg fiodgnameArg
  46. ioctlFIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg))
  47. )
  48. func ptsname(f *os.File) (string, error) {
  49. master, err := isptmaster(f.Fd())
  50. if err != nil {
  51. return "", err
  52. }
  53. if !master {
  54. return "", syscall.EINVAL
  55. }
  56. const n = _C_SPECNAMELEN + 1
  57. var (
  58. buf = make([]byte, n)
  59. arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))}
  60. )
  61. if err := ioctl(f.Fd(), ioctlFIODGNAME, uintptr(unsafe.Pointer(&arg))); err != nil {
  62. return "", err
  63. }
  64. for i, c := range buf {
  65. if c == 0 {
  66. return string(buf[:i]), nil
  67. }
  68. }
  69. return "", errors.New("FIODGNAME string not NUL-terminated")
  70. }