OSDN Git Service

feat(warder): add warder backbone (#181)
[bytom/vapor.git] / vendor / github.com / mattn / go-isatty / isatty_windows.go
1 // +build windows
2 // +build !appengine
3
4 package isatty
5
6 import (
7         "strings"
8         "syscall"
9         "unicode/utf16"
10         "unsafe"
11 )
12
13 const (
14         fileNameInfo uintptr = 2
15         fileTypePipe         = 3
16 )
17
18 var (
19         kernel32                         = syscall.NewLazyDLL("kernel32.dll")
20         procGetConsoleMode               = kernel32.NewProc("GetConsoleMode")
21         procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
22         procGetFileType                  = kernel32.NewProc("GetFileType")
23 )
24
25 func init() {
26         // Check if GetFileInformationByHandleEx is available.
27         if procGetFileInformationByHandleEx.Find() != nil {
28                 procGetFileInformationByHandleEx = nil
29         }
30 }
31
32 // IsTerminal return true if the file descriptor is terminal.
33 func IsTerminal(fd uintptr) bool {
34         var st uint32
35         r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
36         return r != 0 && e == 0
37 }
38
39 // Check pipe name is used for cygwin/msys2 pty.
40 // Cygwin/MSYS2 PTY has a name like:
41 //   \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
42 func isCygwinPipeName(name string) bool {
43         token := strings.Split(name, "-")
44         if len(token) < 5 {
45                 return false
46         }
47
48         if token[0] != `\msys` && token[0] != `\cygwin` {
49                 return false
50         }
51
52         if token[1] == "" {
53                 return false
54         }
55
56         if !strings.HasPrefix(token[2], "pty") {
57                 return false
58         }
59
60         if token[3] != `from` && token[3] != `to` {
61                 return false
62         }
63
64         if token[4] != "master" {
65                 return false
66         }
67
68         return true
69 }
70
71 // IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
72 // terminal.
73 func IsCygwinTerminal(fd uintptr) bool {
74         if procGetFileInformationByHandleEx == nil {
75                 return false
76         }
77
78         // Cygwin/msys's pty is a pipe.
79         ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
80         if ft != fileTypePipe || e != 0 {
81                 return false
82         }
83
84         var buf [2 + syscall.MAX_PATH]uint16
85         r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
86                 4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
87                 uintptr(len(buf)*2), 0, 0)
88         if r == 0 || e != 0 {
89                 return false
90         }
91
92         l := *(*uint32)(unsafe.Pointer(&buf))
93         return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
94 }