summaryrefslogtreecommitdiff
path: root/driver/utils
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2017-01-05 17:03:19 -0500
committerBen Gamari <ben@smart-cactus.org>2017-01-10 13:22:30 -0500
commit6fe9b057396b4ace73106dc9c3c7fcb72a216bfa (patch)
tree47f2f6894108367b48e1bb4672688c636b5226b0 /driver/utils
parente94b07dc791960439df18cfa600a2f42fc945336 (diff)
downloadhaskell-6fe9b057396b4ace73106dc9c3c7fcb72a216bfa.tar.gz
Properly detect MinTTY when running GHCi on Windows
Before, we detecting the presence of MinTTY on Windows in a very imprecise way: by checking if the `_` environment variable was set. Not only is this easy to circumvent, but it also yields false positives on terminals like ConEmu. This changes the test to use the `GetFileInformationByHandleEx` function instead, which provides a far more accurate check for MinTTY's presence. I've tested this on PowerShell, MSYS2, Cygwin, ConEmu, and Git Bash, and it does the right thing on each one. Fixes #12958. Test Plan: Run GHCi on many different Windows and MinTTY consoles Reviewers: erikd, Phyx, austin, bgamari Reviewed By: Phyx, bgamari Subscribers: thomie, #ghc_windows_task_force Differential Revision: https://phabricator.haskell.org/D2878 GHC Trac Issues: #12958
Diffstat (limited to 'driver/utils')
-rw-r--r--driver/utils/isMinTTY.c33
-rw-r--r--driver/utils/isMinTTY.h8
2 files changed, 41 insertions, 0 deletions
diff --git a/driver/utils/isMinTTY.c b/driver/utils/isMinTTY.c
new file mode 100644
index 0000000000..3b3ae27bf3
--- /dev/null
+++ b/driver/utils/isMinTTY.c
@@ -0,0 +1,33 @@
+/*
+ * We need Vista headers to use the GetFileInformationByHandleEx function and
+ * the FILE_NAME_INFO struct.
+ */
+#define WINVER 0x0600
+#define _WIN32_WINNT 0x0600
+
+#include <stdbool.h>
+#include <windows.h>
+#include "isMINTTY.h"
+
+bool isMinTTY() {
+ const HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
+ if (h == NULL || h == INVALID_HANDLE_VALUE) {
+ return false;
+ } else if (GetFileType(h) != FILE_TYPE_PIPE) {
+ return false;
+ }
+
+ const unsigned long bufSize = sizeof(DWORD) + MAX_PATH * sizeof(WCHAR);
+ BYTE buf[bufSize];
+ PFILE_NAME_INFO pfni = (PFILE_NAME_INFO) buf;
+
+ if (!GetFileInformationByHandleEx(h, FileNameInfo, buf, bufSize)) {
+ return false;
+ }
+
+ PWSTR fn = pfni->FileName;
+ fn[pfni->FileNameLength] = L'\0';
+
+ return ((wcsstr(fn, L"\\cygwin-") || wcsstr(fn, L"\\msys-")) &&
+ wcsstr(fn, L"-pty") && wcsstr(fn, L"-master"));
+}
diff --git a/driver/utils/isMinTTY.h b/driver/utils/isMinTTY.h
new file mode 100644
index 0000000000..22e9a473cc
--- /dev/null
+++ b/driver/utils/isMinTTY.h
@@ -0,0 +1,8 @@
+#ifndef ISMINTTY_H
+#define ISMINTTY_H
+
+#include <stdbool.h>
+
+bool isMinTTY();
+
+#endif /* ISMINTTY_H */