vendor/github.com/mattn/go-isatty/isatty_windows.go
author Mikael Berthe <mikael@lilotux.net>
Tue, 23 Aug 2022 22:39:43 +0200
changeset 260 445e01aede7e
parent 251 1c52a0eeb952
permissions -rw-r--r--
Update vendor directory
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents: 251
diff changeset
     1
//go:build windows && !appengine
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents: 251
diff changeset
     2
// +build windows,!appengine
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
package isatty
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     6
import (
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
     7
	"errors"
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
	"strings"
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
	"syscall"
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
	"unicode/utf16"
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
	"unsafe"
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
const (
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    15
	objectNameInfo uintptr = 1
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    16
	fileNameInfo           = 2
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    17
	fileTypePipe           = 3
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
var (
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
	kernel32                         = syscall.NewLazyDLL("kernel32.dll")
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    22
	ntdll                            = syscall.NewLazyDLL("ntdll.dll")
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
	procGetConsoleMode               = kernel32.NewProc("GetConsoleMode")
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
	procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
	procGetFileType                  = kernel32.NewProc("GetFileType")
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    26
	procNtQueryObject                = ntdll.NewProc("NtQueryObject")
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
func init() {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
	// Check if GetFileInformationByHandleEx is available.
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
	if procGetFileInformationByHandleEx.Find() != nil {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
		procGetFileInformationByHandleEx = nil
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
// IsTerminal return true if the file descriptor is terminal.
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
func IsTerminal(fd uintptr) bool {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
	var st uint32
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
	return r != 0 && e == 0
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
// Check pipe name is used for cygwin/msys2 pty.
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
// Cygwin/MSYS2 PTY has a name like:
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
//   \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
func isCygwinPipeName(name string) bool {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
	token := strings.Split(name, "-")
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
	if len(token) < 5 {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    52
	if token[0] != `\msys` &&
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    53
		token[0] != `\cygwin` &&
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    54
		token[0] != `\Device\NamedPipe\msys` &&
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    55
		token[0] != `\Device\NamedPipe\cygwin` {
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
	if token[1] == "" {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    62
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
	if !strings.HasPrefix(token[2], "pty") {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    64
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
	if token[3] != `from` && token[3] != `to` {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
	if token[4] != "master" {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
	return true
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    78
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents: 251
diff changeset
    79
// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    80
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    81
// Windows vista to 10
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    82
// see https://stackoverflow.com/a/18792477 for details
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    83
func getFileNameByHandle(fd uintptr) (string, error) {
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    84
	if procNtQueryObject == nil {
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    85
		return "", errors.New("ntdll.dll: NtQueryObject not supported")
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    86
	}
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    87
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    88
	var buf [4 + syscall.MAX_PATH]uint16
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    89
	var result int
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    90
	r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5,
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    91
		fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0)
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    92
	if r != 0 {
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    93
		return "", e
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    94
	}
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    95
	return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    96
}
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
    97
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
// terminal.
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
func IsCygwinTerminal(fd uintptr) bool {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
	if procGetFileInformationByHandleEx == nil {
251
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
   102
		name, err := getFileNameByHandle(fd)
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
   103
		if err != nil {
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
   104
			return false
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
   105
		}
1c52a0eeb952 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents: 242
diff changeset
   106
		return isCygwinPipeName(name)
242
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
	// Cygwin/msys's pty is a pipe.
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
	ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
	if ft != fileTypePipe || e != 0 {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
	var buf [2 + syscall.MAX_PATH]uint16
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
	r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
		4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   118
		uintptr(len(buf)*2), 0, 0)
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   119
	if r == 0 || e != 0 {
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   120
		return false
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   121
	}
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   122
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   123
	l := *(*uint32)(unsafe.Pointer(&buf))
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   124
	return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
2a9ec03fe5a1 Use vendoring for backward compatibility
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   125
}