github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/os/signal/internal/pty/pty.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build aix darwin dragonfly freebsd hurd linux,!android netbsd openbsd solaris 6 // +build cgo 7 8 // Package pty is a simple pseudo-terminal package for Unix systems, 9 // implemented by calling C functions via cgo. 10 // This is only used for testing the os/signal package. 11 package pty 12 13 import ( 14 "fmt" 15 "os" 16 "syscall" 17 "unsafe" 18 ) 19 20 //extern posix_openpt 21 func posix_openpt(int32) int32 22 23 //extern grantpt 24 func grantpt(int32) int32 25 26 //extern unlockpt 27 func unlockpt(int32) int32 28 29 //extern ptsname 30 func ptsname(int32) *byte 31 32 //extern close 33 func close(int32) int32 34 35 const _O_RDWR = 2 36 37 type PtyError struct { 38 FuncName string 39 ErrorString string 40 Errno syscall.Errno 41 } 42 43 func ptyError(name string, err error) *PtyError { 44 return &PtyError{name, err.Error(), err.(syscall.Errno)} 45 } 46 47 func (e *PtyError) Error() string { 48 return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString) 49 } 50 51 func (e *PtyError) Unwrap() error { return e.Errno } 52 53 // Open returns a master pty and the name of the linked slave tty. 54 func Open() (master *os.File, slave string, err error) { 55 m := posix_openpt(_O_RDWR) 56 if m < 0 { 57 return nil, "", ptyError("posix_openpt", syscall.GetErrno()) 58 } 59 if grantpt(m) < 0 { 60 errno := syscall.GetErrno() 61 close(m) 62 return nil, "", ptyError("grantpt", errno) 63 } 64 if unlockpt(m) < 0 { 65 errno := syscall.GetErrno() 66 close(m) 67 return nil, "", ptyError("unlockpt", errno) 68 } 69 p := ptsname(m) 70 s := (*[32000]byte)(unsafe.Pointer(p))[:] 71 for i, v := range s { 72 if v == 0 { 73 s = s[:i:i] 74 break 75 } 76 } 77 slave = string(s) 78 return os.NewFile(uintptr(m), "pty-master"), slave, nil 79 }