|
12 | 12 | * with Unicode support. |
13 | 13 | *****************************************************************************/ |
14 | 14 | #include <windows.h> |
| 15 | +#include <errno.h> |
15 | 16 | #include <stdio.h> |
16 | 17 | #include <stdlib.h> |
17 | 18 | #include <string.h> |
|
36 | 37 | # endif |
37 | 38 | #endif |
38 | 39 |
|
| 40 | + |
| 41 | +/************************************************************************************************************/ |
| 42 | +/* few addtional definitions for those having older include files especially #include <fileextd.h> */ |
| 43 | +/************************************************************************************************************/ |
| 44 | +#if (WINVER < 0x0600) |
| 45 | + /*Copied from winbase.h*/ |
| 46 | + typedef struct _FILE_NAME_INFO { |
| 47 | + DWORD FileNameLength; |
| 48 | + WCHAR FileName[1]; |
| 49 | + } FILE_NAME_INFO, *PFILE_NAME_INFO; |
| 50 | + typedef enum _FILE_INFO_BY_HANDLE_CLASS { |
| 51 | + FileBasicInfo = 0, |
| 52 | + FileStandardInfo = 1, |
| 53 | + FileNameInfo = 2, |
| 54 | + FileRenameInfo = 3, |
| 55 | + FileDispositionInfo = 4, |
| 56 | + FileAllocationInfo = 5, |
| 57 | + FileEndOfFileInfo = 6, |
| 58 | + FileStreamInfo = 7, |
| 59 | + FileCompressionInfo = 8, |
| 60 | + FileAttributeTagInfo = 9, |
| 61 | + FileIdBothDirectoryInfo = 10, // 0xA |
| 62 | + FileIdBothDirectoryRestartInfo = 11, // 0xB |
| 63 | + FileIoPriorityHintInfo = 12, // 0xC |
| 64 | + FileRemoteProtocolInfo = 13, // 0xD |
| 65 | + FileFullDirectoryInfo = 14, // 0xE |
| 66 | + FileFullDirectoryRestartInfo = 15, // 0xF |
| 67 | + FileStorageInfo = 16, // 0x10 |
| 68 | + FileAlignmentInfo = 17, // 0x11 |
| 69 | + FileIdInfo = 18, // 0x12 |
| 70 | + FileIdExtdDirectoryInfo = 19, // 0x13 |
| 71 | + FileIdExtdDirectoryRestartInfo = 20, // 0x14 |
| 72 | + MaximumFileInfoByHandlesClass |
| 73 | + } FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS; |
| 74 | +#endif //(WINVER < 0x0600) |
| 75 | + |
39 | 76 | #if !defined(IMAGE_SIZEOF_NT_OPTIONAL_HEADER) |
40 | 77 | #include <winnt.h> |
41 | 78 | #define IMAGE_SIZEOF_NT_OPTIONAL_HEADER sizeof(IMAGE_OPTIONAL_HEADER) |
@@ -833,6 +870,99 @@ getVersionInfo(int verbose) |
833 | 870 | */ |
834 | 871 | #define exit(ec) do { _cexit(ec); ExitProcess(ec); } while (0) |
835 | 872 |
|
| 873 | + /* |
| 874 | + * Allow to test if the standard input/output files are from a console or not |
| 875 | + * Inspired of: https://fossies.org/linux/misc/vim-8.0.tar.bz2/vim80/src/iscygpty.c?m=t |
| 876 | + * Return values: |
| 877 | + * -1 - Error |
| 878 | + * 0 - no console (windows only) |
| 879 | + * 1 - normal terminal (unix terminal / windows console) |
| 880 | + * 2 - pipe |
| 881 | + * 3 - file |
| 882 | + * 4 - cygwin terminal (windows only) |
| 883 | + */ |
| 884 | +sqInt fileHandleType(HANDLE fdHandle) { |
| 885 | + if (fdHandle == INVALID_HANDLE_VALUE) { |
| 886 | + return -1; |
| 887 | + } |
| 888 | + |
| 889 | + /* In case of Windows Shell case */ |
| 890 | + DWORD fileType = GetFileType(fdHandle); |
| 891 | + if (fileType == FILE_TYPE_CHAR) |
| 892 | + /* The specified file is a character file, typically an LPT device or a console. */ |
| 893 | + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa364960(v=vs.85).aspx */ |
| 894 | + return 1; |
| 895 | + |
| 896 | + /* In case of Unix emulator, we need to parse the name of the pipe */ |
| 897 | + |
| 898 | + /* Cygwin/msys's pty is a pipe. */ |
| 899 | + if (fileType != FILE_TYPE_PIPE) { |
| 900 | + if (fileType == FILE_TYPE_DISK) |
| 901 | + return 3; //We have a file here |
| 902 | + if (fileType == FILE_TYPE_UNKNOWN && GetLastError() == ERROR_INVALID_HANDLE) |
| 903 | + return 0; //No stdio allocated |
| 904 | + return -1; |
| 905 | + } |
| 906 | + |
| 907 | + int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; |
| 908 | + FILE_NAME_INFO *nameinfo; |
| 909 | + WCHAR *p = NULL; |
| 910 | + |
| 911 | + typedef BOOL(WINAPI *pfnGetFileInformationByHandleEx)( |
| 912 | + HANDLE hFile, |
| 913 | + FILE_INFO_BY_HANDLE_CLASS FileInformationClass, |
| 914 | + LPVOID lpFileInformation, |
| 915 | + DWORD dwBufferSize |
| 916 | + ); |
| 917 | + static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL; |
| 918 | + if (!pGetFileInformationByHandleEx) { |
| 919 | + pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx) |
| 920 | + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetFileInformationByHandleEx"); |
| 921 | + if (!pGetFileInformationByHandleEx) |
| 922 | + return -1; |
| 923 | + } |
| 924 | + |
| 925 | + nameinfo = malloc(size); |
| 926 | + if (nameinfo == NULL) { |
| 927 | + return -1; |
| 928 | + } |
| 929 | + /* Check the name of the pipe: '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' */ |
| 930 | + if (pGetFileInformationByHandleEx(fdHandle, FileNameInfo, nameinfo, size)) { |
| 931 | + nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; |
| 932 | + p = nameinfo->FileName; |
| 933 | + //Check that the pipe name contains msys or cygwin |
| 934 | + if ((((wcsstr(p, L"msys-") || wcsstr(p, L"cygwin-"))) && |
| 935 | + (wcsstr(p, L"-pty") && wcsstr(p, L"-master")))) { |
| 936 | + //The openned pipe is a msys xor cygwin pipe to pty |
| 937 | + free(nameinfo); |
| 938 | + return 4; |
| 939 | + } |
| 940 | + else |
| 941 | + free(nameinfo); |
| 942 | + return 2; //else it is just a standard pipe |
| 943 | + } |
| 944 | + free(nameinfo); |
| 945 | + return -1; |
| 946 | +} |
| 947 | + |
| 948 | +/* |
| 949 | +* Allow to test whether the file handle is from a console or not |
| 950 | +* 1 if one of the stdio is redirected to a console pipe, else 0 (and in this case, a file should be created) |
| 951 | +*/ |
| 952 | +sqInt isFileHandleATTY(HANDLE fdHandle) { |
| 953 | + sqInt res = fileHandleType(fdHandle) ; |
| 954 | + return res == 1 || res == 4; |
| 955 | +} |
| 956 | + |
| 957 | +/* |
| 958 | +* Allow to test whether one of the standard input/output files is from a console or not |
| 959 | +* 1 if one of the stdio is redirected to a console pipe, else 0 (and in this case, a file should be created) |
| 960 | +*/ |
| 961 | +sqInt isOneStdioDescriptorATTY() { |
| 962 | + return isFileHandleATTY(GetStdHandle(STD_INPUT_HANDLE)) || |
| 963 | + isFileHandleATTY(GetStdHandle(STD_OUTPUT_HANDLE)) || isFileHandleATTY(GetStdHandle(STD_ERROR_HANDLE)); |
| 964 | +} |
| 965 | + |
836 | 966 | static void |
837 | 967 | versionInfo(void) |
838 | 968 | { |
@@ -1590,23 +1720,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) |
1590 | 1720 | * allocation failures unless running as a console app because doing so |
1591 | 1721 | * via a MessageBox will make the system unusable. |
1592 | 1722 | */ |
1593 | | -#if 0 /* This way used to work. Does no longer. */ |
1594 | | - DWORD mode; |
1595 | | - |
1596 | | - fIsConsole = GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode); |
1597 | | -#elif 0 /* This does /not/ work with STD_INPUT_HANDLE or STD_OUTPUT_HANDLE */ |
1598 | | - CONSOLE_SCREEN_BUFFER_INFO csbi; |
1599 | | - |
1600 | | - if ((fIsConsole = GetConsoleScreenBufferInfo |
1601 | | - (GetStdHandle(STD_INPUT_HANDLE), &csbi))) |
1602 | | - fIsConsole = csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y; |
1603 | | -#else /* This /does/ work; see */ |
1604 | | - /* https://stackoverflow.com/questions/9009333/how-to-check-if-the-program-is-run-from-a-console */ |
1605 | | - HWND consoleWnd = GetConsoleWindow(); |
1606 | | - DWORD dwProcessId; |
1607 | | - GetWindowThreadProcessId(consoleWnd, &dwProcessId); |
1608 | | - fIsConsole = GetCurrentProcessId() != dwProcessId; |
1609 | | -#endif |
| 1723 | + fIsConsole = isOneStdioDescriptorATTY(); |
1610 | 1724 |
|
1611 | 1725 | /* a few things which need to be done first */ |
1612 | 1726 | gatherSystemInfo(); |
|
0 commit comments