95 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build windows
 | 
						|
// +build !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])))
 | 
						|
}
 |