Skip to content

Commit 6686393

Browse files
lazkaAlexpux
andcommitted
cygpty isatty
Co-authored-by: Алексей <[email protected]>
1 parent 6fbb7d5 commit 6686393

File tree

11 files changed

+248
-12
lines changed

11 files changed

+248
-12
lines changed

Include/iscygpty.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* iscygpty.h -- part of ptycheck
3+
* https://github.com/k-takata/ptycheck
4+
*
5+
* Copyright (c) 2015-2017 K.Takata
6+
*
7+
* You can redistribute it and/or modify it under the terms of either
8+
* the MIT license (as described below) or the Vim license.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining
11+
* a copy of this software and associated documentation files (the
12+
* "Software"), to deal in the Software without restriction, including
13+
* without limitation the rights to use, copy, modify, merge, publish,
14+
* distribute, sublicense, and/or sell copies of the Software, and to
15+
* permit persons to whom the Software is furnished to do so, subject to
16+
* the following conditions:
17+
*
18+
* The above copyright notice and this permission notice shall be
19+
* included in all copies or substantial portions of the Software.
20+
*
21+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28+
*/
29+
30+
#ifndef _ISCYGPTY_H
31+
#define _ISCYGPTY_H
32+
33+
#ifdef _WIN32
34+
int is_cygpty(int fd);
35+
int is_cygpty_used(void);
36+
#else
37+
#define is_cygpty(fd) 0
38+
#define is_cygpty_used() 0
39+
#endif
40+
41+
#endif /* _ISCYGPTY_H */

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ PYTHON_OBJS= \
409409
Python/import.o \
410410
Python/importdl.o \
411411
Python/initconfig.o \
412+
Python/iscygpty.o \
412413
Python/marshal.o \
413414
Python/modsupport.o \
414415
Python/mysnprintf.o \
@@ -1509,6 +1510,7 @@ PYTHON_HEADERS= \
15091510
$(srcdir)/Include/frameobject.h \
15101511
$(srcdir)/Include/import.h \
15111512
$(srcdir)/Include/intrcheck.h \
1513+
$(srcdir)/Include/iscygpty.h \
15121514
$(srcdir)/Include/iterobject.h \
15131515
$(srcdir)/Include/listobject.h \
15141516
$(srcdir)/Include/longobject.h \

Modules/_io/fileio.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#endif
2121
#include <stddef.h> /* For offsetof */
2222
#include "_iomodule.h"
23+
#include "iscygpty.h"
2324

2425
/*
2526
* Known likely problems:
@@ -1129,7 +1130,7 @@ _io_FileIO_isatty_impl(fileio *self)
11291130
return err_closed();
11301131
Py_BEGIN_ALLOW_THREADS
11311132
_Py_BEGIN_SUPPRESS_IPH
1132-
res = isatty(self->fd);
1133+
res = isatty(self->fd) || is_cygpty(self->fd);
11331134
_Py_END_SUPPRESS_IPH
11341135
Py_END_ALLOW_THREADS
11351136
return PyBool_FromLong(res);

Modules/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0()
88
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv()
99
#include "pycore_pystate.h" // _PyInterpreterState_GET()
10+
#include "iscygpty.h"
1011

1112
/* Includes for exit_sigint() */
1213
#include <stdio.h> // perror()
@@ -92,7 +93,7 @@ static inline int config_run_code(const PyConfig *config)
9293
static int
9394
stdin_is_interactive(const PyConfig *config)
9495
{
95-
return (isatty(fileno(stdin)) || config->interactive);
96+
return (isatty(fileno(stdin)) || config->interactive || is_cygpty(fileno(stdin)));
9697
}
9798

9899

Modules/posixmodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#ifdef __ANDROID__
5151
# undef HAVE_FACCESSAT
5252
#endif
53+
#include "iscygpty.h"
5354

5455
#include <stdio.h> // ctermid()
5556
#include <stdlib.h> // system()
@@ -10227,7 +10228,7 @@ os_isatty_impl(PyObject *module, int fd)
1022710228
int return_value;
1022810229
Py_BEGIN_ALLOW_THREADS
1022910230
_Py_BEGIN_SUPPRESS_IPH
10230-
return_value = isatty(fd);
10231+
return_value = isatty(fd) || is_cygpty(fd);
1023110232
_Py_END_SUPPRESS_IPH
1023210233
Py_END_ALLOW_THREADS
1023310234
return return_value;

Objects/fileobject.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define PY_SSIZE_T_CLEAN
44
#include "Python.h"
55
#include "pycore_call.h" // _PyObject_CallNoArgs()
6+
#include "iscygpty.h"
67
#include "pycore_runtime.h" // _PyRuntime
78

89
#if defined(HAVE_GETC_UNLOCKED) && !defined(_Py_MEMORY_SANITIZER)
@@ -387,7 +388,7 @@ stdprinter_isatty(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))
387388
}
388389

389390
Py_BEGIN_ALLOW_THREADS
390-
res = isatty(self->fd);
391+
res = isatty(self->fd) || is_cygpty(self->fd);
391392
Py_END_ALLOW_THREADS
392393

393394
return PyBool_FromLong(res);

Python/bltinmodule.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Built-in functions */
22

33
#include "Python.h"
4+
#include "iscygpty.h"
45
#include <ctype.h>
56
#include "pycore_ast.h" // _PyAST_Validate()
67
#include "pycore_call.h" // _PyObject_CallNoArgs()
@@ -2135,7 +2136,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
21352136
Py_DECREF(tmp);
21362137
if (fd < 0 && PyErr_Occurred())
21372138
return NULL;
2138-
tty = fd == fileno(stdin) && isatty(fd);
2139+
tty = fd == fileno(stdin) && (isatty(fd) || is_cygpty(fd));
21392140
}
21402141
if (tty) {
21412142
tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(fileno));
@@ -2148,7 +2149,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
21482149
Py_DECREF(tmp);
21492150
if (fd < 0 && PyErr_Occurred())
21502151
return NULL;
2151-
tty = fd == fileno(stdout) && isatty(fd);
2152+
tty = fd == fileno(stdout) && (isatty(fd) || is_cygpty(fd));
21522153
}
21532154
}
21542155

Python/fileutils.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "Python.h"
2+
#include "iscygpty.h"
23
#include "pycore_fileutils.h" // fileutils definitions
34
#include "pycore_runtime.h" // _PyRuntime
45
#include "osdefs.h" // SEP
@@ -71,7 +72,7 @@ _Py_device_encoding(int fd)
7172
int valid;
7273
Py_BEGIN_ALLOW_THREADS
7374
_Py_BEGIN_SUPPRESS_IPH
74-
valid = isatty(fd);
75+
valid = isatty(fd) || is_cygpty(fd);
7576
_Py_END_SUPPRESS_IPH
7677
Py_END_ALLOW_THREADS
7778
if (!valid)
@@ -1809,12 +1810,12 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
18091810
depending on heap usage). */
18101811
if (gil_held) {
18111812
Py_BEGIN_ALLOW_THREADS
1812-
if (isatty(fd)) {
1813+
if (isatty(fd) || is_cygpty(fd)) {
18131814
count = 32767;
18141815
}
18151816
Py_END_ALLOW_THREADS
18161817
} else {
1817-
if (isatty(fd)) {
1818+
if (isatty(fd) || is_cygpty(fd)) {
18181819
count = 32767;
18191820
}
18201821
}

Python/frozenmain.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Python.h"
44
#include "pycore_runtime.h" // _PyRuntime_Initialize()
55
#include <locale.h>
6+
#include "iscygpty.h"
67

78
#ifdef MS_WINDOWS
89
extern void PyWinFreeze_ExeInit(void);
@@ -71,7 +72,7 @@ Py_FrozenMain(int argc, char **argv)
7172
sts = 0;
7273
}
7374

74-
if (inspect && isatty((int)fileno(stdin))) {
75+
if (inspect && (isatty((int)fileno(stdin)) || is_cygpty((int)fileno(stdin))))
7576
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
7677
}
7778

Python/iscygpty.c

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* iscygpty.c -- part of ptycheck
3+
* https://github.com/k-takata/ptycheck
4+
*
5+
* Copyright (c) 2015-2017 K.Takata
6+
*
7+
* You can redistribute it and/or modify it under the terms of either
8+
* the MIT license (as described below) or the Vim license.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining
11+
* a copy of this software and associated documentation files (the
12+
* "Software"), to deal in the Software without restriction, including
13+
* without limitation the rights to use, copy, modify, merge, publish,
14+
* distribute, sublicense, and/or sell copies of the Software, and to
15+
* permit persons to whom the Software is furnished to do so, subject to
16+
* the following conditions:
17+
*
18+
* The above copyright notice and this permission notice shall be
19+
* included in all copies or substantial portions of the Software.
20+
*
21+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28+
*/
29+
30+
#ifdef _WIN32
31+
32+
#include <ctype.h>
33+
#include <io.h>
34+
#include <wchar.h>
35+
#include <windows.h>
36+
37+
#ifdef USE_FILEEXTD
38+
/* VC 7.1 or earlier doesn't support SAL. */
39+
# if !defined(_MSC_VER) || (_MSC_VER < 1400)
40+
# define __out
41+
# define __in
42+
# define __in_opt
43+
# endif
44+
/* Win32 FileID API Library:
45+
* http://www.microsoft.com/en-us/download/details.aspx?id=22599
46+
* Needed for WinXP. */
47+
# include <fileextd.h>
48+
#else /* USE_FILEEXTD */
49+
/* VC 8 or earlier. */
50+
# if defined(_MSC_VER) && (_MSC_VER < 1500)
51+
# ifdef ENABLE_STUB_IMPL
52+
# define STUB_IMPL
53+
# else
54+
# error "Win32 FileID API Library is required for VC2005 or earlier."
55+
# endif
56+
# endif
57+
#endif /* USE_FILEEXTD */
58+
59+
60+
#include "iscygpty.h"
61+
62+
//#define USE_DYNFILEID
63+
#ifdef USE_DYNFILEID
64+
typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)(
65+
HANDLE hFile,
66+
FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
67+
LPVOID lpFileInformation,
68+
DWORD dwBufferSize
69+
);
70+
static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL;
71+
72+
# ifndef USE_FILEEXTD
73+
static BOOL WINAPI stub_GetFileInformationByHandleEx(
74+
HANDLE hFile,
75+
FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
76+
LPVOID lpFileInformation,
77+
DWORD dwBufferSize
78+
)
79+
{
80+
return FALSE;
81+
}
82+
# endif
83+
84+
static void setup_fileid_api(void)
85+
{
86+
if (pGetFileInformationByHandleEx != NULL) {
87+
return;
88+
}
89+
pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx)
90+
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
91+
"GetFileInformationByHandleEx");
92+
if (pGetFileInformationByHandleEx == NULL) {
93+
# ifdef USE_FILEEXTD
94+
pGetFileInformationByHandleEx = GetFileInformationByHandleEx;
95+
# else
96+
pGetFileInformationByHandleEx = stub_GetFileInformationByHandleEx;
97+
# endif
98+
}
99+
}
100+
#else
101+
# define pGetFileInformationByHandleEx GetFileInformationByHandleEx
102+
# define setup_fileid_api()
103+
#endif
104+
105+
106+
#define is_wprefix(s, prefix) \
107+
(wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
108+
109+
/* Check if the fd is a cygwin/msys's pty. */
110+
int is_cygpty(int fd)
111+
{
112+
#ifdef STUB_IMPL
113+
return 0;
114+
#else
115+
HANDLE h;
116+
int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * (MAX_PATH - 1);
117+
FILE_NAME_INFO *nameinfo;
118+
WCHAR *p = NULL;
119+
120+
setup_fileid_api();
121+
122+
h = (HANDLE) _get_osfhandle(fd);
123+
if (h == INVALID_HANDLE_VALUE) {
124+
return 0;
125+
}
126+
/* Cygwin/msys's pty is a pipe. */
127+
if (GetFileType(h) != FILE_TYPE_PIPE) {
128+
return 0;
129+
}
130+
nameinfo = malloc(size + sizeof(WCHAR));
131+
if (nameinfo == NULL) {
132+
return 0;
133+
}
134+
/* Check the name of the pipe:
135+
* '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' */
136+
if (pGetFileInformationByHandleEx(h, FileNameInfo, nameinfo, size)) {
137+
nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
138+
p = nameinfo->FileName;
139+
if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
140+
p += 8;
141+
} else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
142+
p += 6;
143+
} else {
144+
p = NULL;
145+
}
146+
if (p != NULL) {
147+
while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
148+
++p;
149+
if (is_wprefix(p, L"-pty")) {
150+
p += 4;
151+
} else {
152+
p = NULL;
153+
}
154+
}
155+
if (p != NULL) {
156+
while (*p && isdigit(*p)) /* Skip pty number. */
157+
++p;
158+
if (is_wprefix(p, L"-from-master")) {
159+
//p += 12;
160+
} else if (is_wprefix(p, L"-to-master")) {
161+
//p += 10;
162+
} else {
163+
p = NULL;
164+
}
165+
}
166+
}
167+
free(nameinfo);
168+
return (p != NULL);
169+
#endif /* STUB_IMPL */
170+
}
171+
172+
/* Check if at least one cygwin/msys pty is used. */
173+
int is_cygpty_used(void)
174+
{
175+
int fd, ret = 0;
176+
177+
for (fd = 0; fd < 3; fd++) {
178+
ret |= is_cygpty(fd);
179+
}
180+
return ret;
181+
}
182+
183+
#endif /* _WIN32 */
184+
185+
/* vim: set ts=4 sw=4: */

0 commit comments

Comments
 (0)