12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- //go:build windows && !appengine
- // +build windows,!appengine
- package isatty
- import (
- "strings"
- "syscall"
- "unicode/utf16"
- "unsafe"
- )
- const (
- fileNameInfo uintptr = 2
- fileTypePipe = 3
- )
- var (
- kernel32 = syscall.NewLazyDLL("kernel32.dll")
- procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
- procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
- procGetFileType = kernel32.NewProc("GetFileType")
- )
- func init() {
- // Check if GetFileInformationByHandleEx is available.
- if procGetFileInformationByHandleEx.Find() != nil {
- procGetFileInformationByHandleEx = nil
- }
- }
- // IsTerminal return true if the file descriptor is terminal.
- func IsTerminal(fd uintptr) bool {
- var st uint32
- r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
- return r != 0 && e == 0
- }
- // Check pipe name is used for cygwin/msys2 pty.
- // Cygwin/MSYS2 PTY has a name like:
- // \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
- func isCygwinPipeName(name string) bool {
- token := strings.Split(name, "-")
- if len(token) < 5 {
- return false
- }
- if token[0] != `\msys` && token[0] != `\cygwin` {
- return false
- }
- if token[1] == "" {
- return false
- }
- if !strings.HasPrefix(token[2], "pty") {
- return false
- }
- if token[3] != `from` && token[3] != `to` {
- return false
- }
- if token[4] != "master" {
- return false
- }
- return true
- }
- // IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
- // terminal.
- func IsCygwinTerminal(fd uintptr) bool {
- if procGetFileInformationByHandleEx == nil {
- return false
- }
- // Cygwin/msys's pty is a pipe.
- ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
- if ft != fileTypePipe || e != 0 {
- return false
- }
- var buf [2 + syscall.MAX_PATH]uint16
- r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
- 4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
- uintptr(len(buf)*2), 0, 0)
- if r == 0 || e != 0 {
- return false
- }
- l := *(*uint32)(unsafe.Pointer(&buf))
- return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
- }
|