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  }