github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/pkg/term/tc_solaris_cgo.go (about)

     1  // +build solaris,cgo
     2  
     3  package term
     4  
     5  import (
     6  	"syscall"
     7  	"unsafe"
     8  
     9  	"golang.org/x/sys/unix"
    10  )
    11  
    12  // #include <termios.h>
    13  import "C"
    14  
    15  // Termios is the Unix API for terminal I/O.
    16  // It is passthrough for unix.Termios in order to make it portable with
    17  // other platforms where it is not available or handled differently.
    18  type Termios unix.Termios
    19  
    20  // MakeRaw put the terminal connected to the given file descriptor into raw
    21  // mode and returns the previous state of the terminal so that it can be
    22  // restored.
    23  func MakeRaw(fd uintptr) (*State, error) {
    24  	var oldState State
    25  	if err := tcget(fd, &oldState.termios); err != 0 {
    26  		return nil, err
    27  	}
    28  
    29  	newState := oldState.termios
    30  
    31  	newState.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON | unix.IXANY)
    32  	newState.Oflag &^= unix.OPOST
    33  	newState.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
    34  	newState.Cflag &^= (unix.CSIZE | unix.PARENB)
    35  	newState.Cflag |= unix.CS8
    36  
    37  	/*
    38  		VMIN is the minimum number of characters that needs to be read in non-canonical mode for it to be returned
    39  		Since VMIN is overloaded with another element in canonical mode when we switch modes it defaults to 4. It
    40  		needs to be explicitly set to 1.
    41  	*/
    42  	newState.Cc[C.VMIN] = 1
    43  	newState.Cc[C.VTIME] = 0
    44  
    45  	if err := tcset(fd, &newState); err != 0 {
    46  		return nil, err
    47  	}
    48  	return &oldState, nil
    49  }
    50  
    51  func tcget(fd uintptr, p *Termios) syscall.Errno {
    52  	ret, err := C.tcgetattr(C.int(fd), (*C.struct_termios)(unsafe.Pointer(p)))
    53  	if ret != 0 {
    54  		return err.(syscall.Errno)
    55  	}
    56  	return 0
    57  }
    58  
    59  func tcset(fd uintptr, p *Termios) syscall.Errno {
    60  	ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(p)))
    61  	if ret != 0 {
    62  		return err.(syscall.Errno)
    63  	}
    64  	return 0
    65  }