Mercurial > gnulib
comparison lib/isatty.c @ 40236:e3496deebf30
isatty: Make it return true in Cygwin consoles on native Windows.
* lib/isatty.c: Include <string.h>.
(GetProcAddress): New macro.
(GetNamedPipeClientProcessIdFuncType): New type.
(GetNamedPipeClientProcessIdFunc): New variable.
(QueryFullProcessImageNameFuncType): New type.
(QueryFullProcessImageNameFunc): New variable.
(initialized): New variable.
(initialize): New function.
(IsCygwinConsoleHandle): New function.
(isatty): Invoke it.
* doc/posix-functions/isatty.texi: Mention the issue.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 14 Mar 2019 23:54:28 +0100 |
parents | b06060465f09 |
children |
comparison
equal
deleted
inserted
replaced
40235:5a52ef2d4772 | 40236:e3496deebf30 |
---|---|
20 #include <unistd.h> | 20 #include <unistd.h> |
21 | 21 |
22 /* This replacement is enabled on native Windows. */ | 22 /* This replacement is enabled on native Windows. */ |
23 | 23 |
24 #include <errno.h> | 24 #include <errno.h> |
25 #include <string.h> | |
25 | 26 |
26 /* Get declarations of the Win32 API functions. */ | 27 /* Get declarations of the Win32 API functions. */ |
27 #define WIN32_LEAN_AND_MEAN | 28 #define WIN32_LEAN_AND_MEAN |
28 #include <windows.h> | 29 #include <windows.h> |
29 | 30 |
36 # include "msvc-nothrow.h" | 37 # include "msvc-nothrow.h" |
37 #else | 38 #else |
38 # include <io.h> | 39 # include <io.h> |
39 #endif | 40 #endif |
40 | 41 |
42 /* Avoid warnings from gcc -Wcast-function-type. */ | |
43 #define GetProcAddress \ | |
44 (void *) GetProcAddress | |
45 | |
46 /* GetNamedPipeClientProcessId was introduced only in Windows Vista. */ | |
47 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFuncType) (HANDLE hPipe, | |
48 PULONG pClientProcessId); | |
49 static GetNamedPipeClientProcessIdFuncType GetNamedPipeClientProcessIdFunc = NULL; | |
50 /* QueryFullProcessImageName was introduced only in Windows Vista. */ | |
51 typedef BOOL (WINAPI * QueryFullProcessImageNameFuncType) (HANDLE hProcess, | |
52 DWORD dwFlags, | |
53 LPSTR lpExeName, | |
54 PDWORD pdwSize); | |
55 static QueryFullProcessImageNameFuncType QueryFullProcessImageNameFunc = NULL; | |
56 static BOOL initialized = FALSE; | |
57 | |
58 static void | |
59 initialize (void) | |
60 { | |
61 HMODULE kernel32 = LoadLibrary ("kernel32.dll"); | |
62 if (kernel32 != NULL) | |
63 { | |
64 GetNamedPipeClientProcessIdFunc = | |
65 (GetNamedPipeClientProcessIdFuncType) GetProcAddress (kernel32, "GetNamedPipeClientProcessId"); | |
66 QueryFullProcessImageNameFunc = | |
67 (QueryFullProcessImageNameFuncType) GetProcAddress (kernel32, "QueryFullProcessImageNameA"); | |
68 } | |
69 initialized = TRUE; | |
70 } | |
71 | |
41 static BOOL IsConsoleHandle (HANDLE h) | 72 static BOOL IsConsoleHandle (HANDLE h) |
42 { | 73 { |
43 DWORD mode; | 74 DWORD mode; |
75 /* GetConsoleMode | |
76 <https://docs.microsoft.com/en-us/windows/console/getconsolemode> */ | |
44 return GetConsoleMode (h, &mode) != 0; | 77 return GetConsoleMode (h, &mode) != 0; |
78 } | |
79 | |
80 static BOOL IsCygwinConsoleHandle (HANDLE h) | |
81 { | |
82 /* A handle to a Cygwin console is in fact a named pipe whose client process | |
83 and server process is <CYGWIN_INSTALL_DIR>\bin\mintty.exe. */ | |
84 BOOL result = FALSE; | |
85 ULONG processId; | |
86 | |
87 if (!initialized) | |
88 initialize (); | |
89 | |
90 /* GetNamedPipeClientProcessId | |
91 <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getnamedpipeclientprocessid> | |
92 It requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ | |
93 if (GetNamedPipeClientProcessIdFunc && QueryFullProcessImageNameFunc | |
94 && GetNamedPipeClientProcessIdFunc (h, &processId)) | |
95 { | |
96 /* OpenProcess | |
97 <https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocess> */ | |
98 HANDLE processHandle = | |
99 OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId); | |
100 if (processHandle != NULL) | |
101 { | |
102 char buf[1024]; | |
103 DWORD bufsize = sizeof (buf); | |
104 /* The file name can be determined through | |
105 GetProcessImageFileName | |
106 <https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-getprocessimagefilenamea> | |
107 or | |
108 QueryFullProcessImageName | |
109 <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-queryfullprocessimagenamea> | |
110 The former returns a file name in non-standard notation (it starts | |
111 with '\Device\') and may require linking with psapi.dll. | |
112 The latter is better, but requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA | |
113 or higher. */ | |
114 if (QueryFullProcessImageNameFunc (processHandle, 0, buf, &bufsize)) | |
115 { | |
116 if (strlen (buf) >= 11 | |
117 && strcmp (buf + strlen (buf) - 11, "\\mintty.exe") == 0) | |
118 result = TRUE; | |
119 } | |
120 CloseHandle (processHandle); | |
121 } | |
122 } | |
123 return result; | |
45 } | 124 } |
46 | 125 |
47 #if HAVE_MSVC_INVALID_PARAMETER_HANDLER | 126 #if HAVE_MSVC_INVALID_PARAMETER_HANDLER |
48 static int | 127 static int |
49 _isatty_nothrow (int fd) | 128 _isatty_nothrow (int fd) |
82 if (_isatty_nothrow (fd)) | 161 if (_isatty_nothrow (fd)) |
83 { | 162 { |
84 if (IsConsoleHandle (h)) | 163 if (IsConsoleHandle (h)) |
85 return 1; | 164 return 1; |
86 } | 165 } |
166 if (IsCygwinConsoleHandle (h)) | |
167 return 1; | |
87 errno = ENOTTY; | 168 errno = ENOTTY; |
88 return 0; | 169 return 0; |
89 } | 170 } |