mirror of https://github.com/EasyDarwin/EasyDarwin
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.1 KiB
94 lines
2.1 KiB
// +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]))) |
|
}
|
|
|