github.com/dolfly/pty@v1.2.1/pty_netbsd.go (about) 1 //go:build netbsd 2 //+build netbsd 3 4 package pty 5 6 import ( 7 "errors" 8 "os" 9 "syscall" 10 "unsafe" 11 ) 12 13 func open() (pty, tty *os.File, err error) { 14 p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) 15 if err != nil { 16 return nil, nil, err 17 } 18 // In case of error after this point, make sure we close the ptmx fd. 19 defer func() { 20 if err != nil { 21 _ = p.Close() // Best effort. 22 } 23 }() 24 25 sname, err := ptsname(p) 26 if err != nil { 27 return nil, nil, err 28 } 29 30 if err := grantpt(p); err != nil { 31 return nil, nil, err 32 } 33 34 // In NetBSD unlockpt() does nothing, so it isn't called here. 35 36 t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) 37 if err != nil { 38 return nil, nil, err 39 } 40 return p, t, nil 41 } 42 43 func ptsname(f *os.File) (string, error) { 44 /* 45 * from ptsname(3): The ptsname() function is equivalent to: 46 * struct ptmget pm; 47 * ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn; 48 */ 49 var ptm ptmget 50 if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil { 51 return "", err 52 } 53 name := make([]byte, len(ptm.Sn)) 54 for i, c := range ptm.Sn { 55 name[i] = byte(c) 56 if c == 0 { 57 return string(name[:i]), nil 58 } 59 } 60 return "", errors.New("TIOCPTSNAME string not NUL-terminated") 61 } 62 63 func grantpt(f *os.File) error { 64 /* 65 * from grantpt(3): Calling grantpt() is equivalent to: 66 * ioctl(fd, TIOCGRANTPT, 0); 67 */ 68 return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0) 69 }