]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/mattn/go-isatty/isatty_windows.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / mattn / go-isatty / isatty_windows.go
index 83c398b16db4d4013aae61d0048ddfbf73fd4816..af51cbcaa4853196e055d1ca1c2eb34a440b6918 100644 (file)
@@ -4,12 +4,30 @@
 package isatty
 
 import (
+       "strings"
        "syscall"
+       "unicode/utf16"
        "unsafe"
 )
 
-var kernel32 = syscall.NewLazyDLL("kernel32.dll")
-var procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
+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 {
@@ -17,3 +35,60 @@ func IsTerminal(fd uintptr) bool {
        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])))
+}