1package pty 2 3import ( 4 "errors" 5 "os" 6 "syscall" 7 "unsafe" 8) 9 10func open() (pty, tty *os.File, err error) { 11 p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) 12 if err != nil { 13 return nil, nil, err 14 } 15 16 sname, err := ptsname(p) 17 if err != nil { 18 return nil, nil, err 19 } 20 21 err = grantpt(p) 22 if err != nil { 23 return nil, nil, err 24 } 25 26 err = unlockpt(p) 27 if err != nil { 28 return nil, nil, err 29 } 30 31 t, err := os.OpenFile(sname, os.O_RDWR, 0) 32 if err != nil { 33 return nil, nil, err 34 } 35 return p, t, nil 36} 37 38func ptsname(f *os.File) (string, error) { 39 n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME)) 40 41 err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) 42 if err != nil { 43 return "", err 44 } 45 46 for i, c := range n { 47 if c == 0 { 48 return string(n[:i]), nil 49 } 50 } 51 return "", errors.New("TIOCPTYGNAME string not NUL-terminated") 52} 53 54func grantpt(f *os.File) error { 55 return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0) 56} 57 58func unlockpt(f *os.File) error { 59 return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0) 60} 61