Source file src/os/signal/internal/pty/pty.go

     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  //go:build (aix || darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd) && cgo
     6  
     7  // Package pty is a simple pseudo-terminal package for Unix systems,
     8  // implemented by calling C functions via cgo.
     9  // This is only used for testing the os/signal package.
    10  package pty
    11  
    12  /*
    13  #define _XOPEN_SOURCE 600
    14  #include <fcntl.h>
    15  #include <stdlib.h>
    16  #include <unistd.h>
    17  */
    18  import "C"
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"syscall"
    24  )
    25  
    26  type PtyError struct {
    27  	FuncName    string
    28  	ErrorString string
    29  	Errno       syscall.Errno
    30  }
    31  
    32  func ptyError(name string, err error) *PtyError {
    33  	return &PtyError{name, err.Error(), err.(syscall.Errno)}
    34  }
    35  
    36  func (e *PtyError) Error() string {
    37  	return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString)
    38  }
    39  
    40  func (e *PtyError) Unwrap() error { return e.Errno }
    41  
    42  // Open returns a control pty and the name of the linked process tty.
    43  func Open() (pty *os.File, processTTY string, err error) {
    44  	m, err := C.posix_openpt(C.O_RDWR)
    45  	if err != nil {
    46  		return nil, "", ptyError("posix_openpt", err)
    47  	}
    48  	if _, err := C.grantpt(m); err != nil {
    49  		C.close(m)
    50  		return nil, "", ptyError("grantpt", err)
    51  	}
    52  	if _, err := C.unlockpt(m); err != nil {
    53  		C.close(m)
    54  		return nil, "", ptyError("unlockpt", err)
    55  	}
    56  	processTTY = C.GoString(C.ptsname(m))
    57  	return os.NewFile(uintptr(m), "pty"), processTTY, nil
    58  }
    59  

View as plain text