| 1 | n/a | import array |
|---|
| 2 | n/a | import unittest |
|---|
| 3 | n/a | from test.support import import_module, get_attribute |
|---|
| 4 | n/a | import os, struct |
|---|
| 5 | n/a | fcntl = import_module('fcntl') |
|---|
| 6 | n/a | termios = import_module('termios') |
|---|
| 7 | n/a | get_attribute(termios, 'TIOCGPGRP') #Can't run tests without this feature |
|---|
| 8 | n/a | |
|---|
| 9 | n/a | try: |
|---|
| 10 | n/a | tty = open("/dev/tty", "rb") |
|---|
| 11 | n/a | except OSError: |
|---|
| 12 | n/a | raise unittest.SkipTest("Unable to open /dev/tty") |
|---|
| 13 | n/a | else: |
|---|
| 14 | n/a | # Skip if another process is in foreground |
|---|
| 15 | n/a | r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ") |
|---|
| 16 | n/a | tty.close() |
|---|
| 17 | n/a | rpgrp = struct.unpack("i", r)[0] |
|---|
| 18 | n/a | if rpgrp not in (os.getpgrp(), os.getsid(0)): |
|---|
| 19 | n/a | raise unittest.SkipTest("Neither the process group nor the session " |
|---|
| 20 | n/a | "are attached to /dev/tty") |
|---|
| 21 | n/a | del tty, r, rpgrp |
|---|
| 22 | n/a | |
|---|
| 23 | n/a | try: |
|---|
| 24 | n/a | import pty |
|---|
| 25 | n/a | except ImportError: |
|---|
| 26 | n/a | pty = None |
|---|
| 27 | n/a | |
|---|
| 28 | n/a | class IoctlTests(unittest.TestCase): |
|---|
| 29 | n/a | def test_ioctl(self): |
|---|
| 30 | n/a | # If this process has been put into the background, TIOCGPGRP returns |
|---|
| 31 | n/a | # the session ID instead of the process group id. |
|---|
| 32 | n/a | ids = (os.getpgrp(), os.getsid(0)) |
|---|
| 33 | n/a | with open("/dev/tty", "rb") as tty: |
|---|
| 34 | n/a | r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ") |
|---|
| 35 | n/a | rpgrp = struct.unpack("i", r)[0] |
|---|
| 36 | n/a | self.assertIn(rpgrp, ids) |
|---|
| 37 | n/a | |
|---|
| 38 | n/a | def _check_ioctl_mutate_len(self, nbytes=None): |
|---|
| 39 | n/a | buf = array.array('i') |
|---|
| 40 | n/a | intsize = buf.itemsize |
|---|
| 41 | n/a | ids = (os.getpgrp(), os.getsid(0)) |
|---|
| 42 | n/a | # A fill value unlikely to be in `ids` |
|---|
| 43 | n/a | fill = -12345 |
|---|
| 44 | n/a | if nbytes is not None: |
|---|
| 45 | n/a | # Extend the buffer so that it is exactly `nbytes` bytes long |
|---|
| 46 | n/a | buf.extend([fill] * (nbytes // intsize)) |
|---|
| 47 | n/a | self.assertEqual(len(buf) * intsize, nbytes) # sanity check |
|---|
| 48 | n/a | else: |
|---|
| 49 | n/a | buf.append(fill) |
|---|
| 50 | n/a | with open("/dev/tty", "rb") as tty: |
|---|
| 51 | n/a | r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, 1) |
|---|
| 52 | n/a | rpgrp = buf[0] |
|---|
| 53 | n/a | self.assertEqual(r, 0) |
|---|
| 54 | n/a | self.assertIn(rpgrp, ids) |
|---|
| 55 | n/a | |
|---|
| 56 | n/a | def test_ioctl_mutate(self): |
|---|
| 57 | n/a | self._check_ioctl_mutate_len() |
|---|
| 58 | n/a | |
|---|
| 59 | n/a | def test_ioctl_mutate_1024(self): |
|---|
| 60 | n/a | # Issue #9758: a mutable buffer of exactly 1024 bytes wouldn't be |
|---|
| 61 | n/a | # copied back after the system call. |
|---|
| 62 | n/a | self._check_ioctl_mutate_len(1024) |
|---|
| 63 | n/a | |
|---|
| 64 | n/a | def test_ioctl_mutate_2048(self): |
|---|
| 65 | n/a | # Test with a larger buffer, just for the record. |
|---|
| 66 | n/a | self._check_ioctl_mutate_len(2048) |
|---|
| 67 | n/a | |
|---|
| 68 | n/a | def test_ioctl_signed_unsigned_code_param(self): |
|---|
| 69 | n/a | if not pty: |
|---|
| 70 | n/a | raise unittest.SkipTest('pty module required') |
|---|
| 71 | n/a | mfd, sfd = pty.openpty() |
|---|
| 72 | n/a | try: |
|---|
| 73 | n/a | if termios.TIOCSWINSZ < 0: |
|---|
| 74 | n/a | set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ |
|---|
| 75 | n/a | set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffff |
|---|
| 76 | n/a | else: |
|---|
| 77 | n/a | set_winsz_opcode_pos = termios.TIOCSWINSZ |
|---|
| 78 | n/a | set_winsz_opcode_maybe_neg, = struct.unpack("i", |
|---|
| 79 | n/a | struct.pack("I", termios.TIOCSWINSZ)) |
|---|
| 80 | n/a | |
|---|
| 81 | n/a | our_winsz = struct.pack("HHHH",80,25,0,0) |
|---|
| 82 | n/a | # test both with a positive and potentially negative ioctl code |
|---|
| 83 | n/a | new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz) |
|---|
| 84 | n/a | new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz) |
|---|
| 85 | n/a | finally: |
|---|
| 86 | n/a | os.close(mfd) |
|---|
| 87 | n/a | os.close(sfd) |
|---|
| 88 | n/a | |
|---|
| 89 | n/a | |
|---|
| 90 | n/a | if __name__ == "__main__": |
|---|
| 91 | n/a | unittest.main() |
|---|