Skip to content

Commit e06b18a

Browse files
authored
Emulate fcntl.ioctl for command TIOCGWINSZ (#1888)
1 parent f2ed788 commit e06b18a

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

src/core/IronPython.Modules/fcntl.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,33 @@ a file object.
2727
""";
2828

2929

30+
// supporting fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf)
31+
// where buf = array.array('h', [0, 0, 0, 0])
32+
public static object ioctl(CodeContext context, int fd, int cmd, [NotNone] IBufferProtocol arg, int mutate_flag = 1) {
33+
if (cmd == PythonTermios.TIOCGWINSZ) {
34+
using IPythonBuffer buf = arg.GetBuffer();
35+
36+
Span<short> winsize = stackalloc short[4];
37+
winsize[0] = (short)Console.WindowHeight;
38+
winsize[1] = (short)Console.WindowWidth;
39+
winsize[2] = (short)Console.BufferHeight; // buffer height and width are not accurate on macOS
40+
winsize[3] = (short)Console.BufferWidth;
41+
Span<byte> payload = MemoryMarshal.Cast<short, byte>(winsize);
42+
43+
if (buf.IsReadOnly || mutate_flag == 0) {
44+
byte[] res = buf.ToArray();
45+
payload.Slice(0, Math.Min(payload.Length, res.Length)).CopyTo(res);
46+
return Bytes.Make(res);
47+
} else {
48+
var res = buf.AsSpan();
49+
payload.Slice(0, Math.Min(payload.Length, res.Length)).CopyTo(res);
50+
return 0;
51+
}
52+
}
53+
throw new NotImplementedException($"ioctl: unsupported command {cmd}");
54+
}
55+
56+
3057
// FD Flags
3158
public static int FD_CLOEXEC = 1;
3259
public static int FASYNC => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 0x0040 : 0x2000;

tests/suite/test_builtin_stdlib.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ def load_tests(loader, standard_tests, pattern):
2121
test.test_builtin.BuiltinTest('test_input'),
2222
test.test_builtin.BuiltinTest('test_len'),
2323
test.test_builtin.BuiltinTest('test_open_non_inheritable'), # https://github.com/IronLanguages/ironpython3/issues/1225
24+
]
25+
26+
skip_tests = [
27+
# module `pty` is importable but not functional on .NET Core
2428
test.test_builtin.PtyTests('test_input_no_stdout_fileno'),
2529
test.test_builtin.PtyTests('test_input_tty'),
2630
test.test_builtin.PtyTests('test_input_tty_non_ascii'),
2731
test.test_builtin.PtyTests('test_input_tty_non_ascii_unicode_errors'),
32+
test.test_builtin.ShutdownTest('test_cleanup'),
2833
]
29-
30-
skip_tests = []
3134
if is_netcoreapp:
3235
skip_tests += [
33-
test.test_builtin.ShutdownTest('test_cleanup'),
3436
]
3537

3638
return generate_suite(tests, failing_tests, skip_tests)

0 commit comments

Comments
 (0)