github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/installer/pty.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "os" 7 "strconv" 8 "syscall" 9 "unsafe" 10 11 "github.com/Cloud-Foundations/Dominator/lib/wsyscall" 12 ) 13 14 func openPty() (pty, tty *os.File, err error) { 15 p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) 16 if err != nil { 17 return nil, nil, err 18 } 19 // In case of error after this point, make sure we close the ptmx fd. 20 defer func() { 21 if err != nil { 22 p.Close() // Best effort. 23 } 24 }() 25 sname, err := ptsname(p) 26 if err != nil { 27 return nil, nil, err 28 } 29 if err := unlockpt(p); err != nil { 30 return nil, nil, err 31 } 32 t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) 33 if err != nil { 34 return nil, nil, err 35 } 36 return p, t, nil 37 } 38 39 func ptsname(f *os.File) (string, error) { 40 var n uint32 41 err := wsyscall.Ioctl(int(f.Fd()), syscall.TIOCGPTN, 42 uintptr(unsafe.Pointer(&n))) 43 if err != nil { 44 return "", err 45 } 46 return "/dev/pts/" + strconv.Itoa(int(n)), nil 47 } 48 49 func unlockpt(f *os.File) error { 50 var u int32 51 // Use TIOCSPTLCK with a zero valued arg to clear the slave pty lock. 52 return wsyscall.Ioctl(int(f.Fd()), syscall.TIOCSPTLCK, 53 uintptr(unsafe.Pointer(&u))) 54 }