summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_ioctl.py22
-rw-r--r--Lib/test/test_termios.py9
-rw-r--r--Misc/NEWS.d/next/Library/2024-05-31-12-57-31.gh-issue-119770.NCtels.rst1
-rw-r--r--Modules/termios.c18
4 files changed, 32 insertions, 18 deletions
diff --git a/Lib/test/test_ioctl.py b/Lib/test/test_ioctl.py
index 7b7067e..04934df 100644
--- a/Lib/test/test_ioctl.py
+++ b/Lib/test/test_ioctl.py
@@ -66,23 +66,15 @@ class IoctlTests(unittest.TestCase):
# Test with a larger buffer, just for the record.
self._check_ioctl_mutate_len(2048)
- def test_ioctl_signed_unsigned_code_param(self):
- if not pty:
- raise unittest.SkipTest('pty module required')
+ @unittest.skipIf(pty is None, 'pty module required')
+ def test_ioctl_set_window_size(self):
mfd, sfd = pty.openpty()
try:
- if termios.TIOCSWINSZ < 0:
- set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ
- set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffff
- else:
- set_winsz_opcode_pos = termios.TIOCSWINSZ
- set_winsz_opcode_maybe_neg, = struct.unpack("i",
- struct.pack("I", termios.TIOCSWINSZ))
-
- our_winsz = struct.pack("HHHH",80,25,0,0)
- # test both with a positive and potentially negative ioctl code
- new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
- new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
+ # (rows, columns, xpixel, ypixel)
+ our_winsz = struct.pack("HHHH", 20, 40, 0, 0)
+ result = fcntl.ioctl(mfd, termios.TIOCSWINSZ, our_winsz)
+ new_winsz = struct.unpack("HHHH", result)
+ self.assertEqual(new_winsz[:2], (20, 40))
finally:
os.close(mfd)
os.close(sfd)
diff --git a/Lib/test/test_termios.py b/Lib/test/test_termios.py
index 58698ff..22e397c 100644
--- a/Lib/test/test_termios.py
+++ b/Lib/test/test_termios.py
@@ -211,6 +211,15 @@ class TestModule(unittest.TestCase):
self.assertLess(termios.VTIME, termios.NCCS)
self.assertLess(termios.VMIN, termios.NCCS)
+ def test_ioctl_constants(self):
+ # gh-119770: ioctl() constants must be positive
+ for name in dir(termios):
+ if not name.startswith('TIO'):
+ continue
+ value = getattr(termios, name)
+ with self.subTest(name=name):
+ self.assertGreaterEqual(value, 0)
+
def test_exception(self):
self.assertTrue(issubclass(termios.error, Exception))
self.assertFalse(issubclass(termios.error, OSError))
diff --git a/Misc/NEWS.d/next/Library/2024-05-31-12-57-31.gh-issue-119770.NCtels.rst b/Misc/NEWS.d/next/Library/2024-05-31-12-57-31.gh-issue-119770.NCtels.rst
new file mode 100644
index 0000000..94265e4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-05-31-12-57-31.gh-issue-119770.NCtels.rst
@@ -0,0 +1 @@
+Make :mod:`termios` ``ioctl()`` constants positive. Patch by Victor Stinner.
diff --git a/Modules/termios.c b/Modules/termios.c
index 0633d8f..efb5fcc 100644
--- a/Modules/termios.c
+++ b/Modules/termios.c
@@ -1352,9 +1352,21 @@ termios_exec(PyObject *mod)
}
while (constant->name != NULL) {
- if (PyModule_AddIntConstant(
- mod, constant->name, constant->value) < 0) {
- return -1;
+ if (strncmp(constant->name, "TIO", 3) == 0) {
+ // gh-119770: Convert value to unsigned int for ioctl() constants,
+ // constants can be negative on macOS whereas ioctl() expects an
+ // unsigned long 'request'.
+ unsigned int value = constant->value & UINT_MAX;
+ if (PyModule_Add(mod, constant->name,
+ PyLong_FromUnsignedLong(value)) < 0) {
+ return -1;
+ }
+ }
+ else {
+ if (PyModule_AddIntConstant(
+ mod, constant->name, constant->value) < 0) {
+ return -1;
+ }
}
++constant;
}