github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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 linux,!android netbsd openbsd 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 /* 14 #define _XOPEN_SOURCE 600 15 #include <fcntl.h> 16 #include <stdlib.h> 17 #include <unistd.h> 18 */ 19 import "C" 20 21 import ( 22 "fmt" 23 "os" 24 "syscall" 25 ) 26 27 type PtyError struct { 28 FuncName string 29 ErrorString string 30 Errno syscall.Errno 31 } 32 33 func ptyError(name string, err error) *PtyError { 34 return &PtyError{name, err.Error(), err.(syscall.Errno)} 35 } 36 37 func (e *PtyError) Error() string { 38 return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString) 39 } 40 41 func (e *PtyError) Unwrap() error { return e.Errno } 42 43 // Open returns a control pty and the name of the linked process tty. 44 func Open() (pty *os.File, processTTY string, err error) { 45 m, err := C.posix_openpt(C.O_RDWR) 46 if err != nil { 47 return nil, "", ptyError("posix_openpt", err) 48 } 49 if _, err := C.grantpt(m); err != nil { 50 C.close(m) 51 return nil, "", ptyError("grantpt", err) 52 } 53 if _, err := C.unlockpt(m); err != nil { 54 C.close(m) 55 return nil, "", ptyError("unlockpt", err) 56 } 57 processTTY = C.GoString(C.ptsname(m)) 58 return os.NewFile(uintptr(m), "pty"), processTTY, nil 59 }