ioctl I_PUSH on a pty ignores O_NOCTTY and acquires it as controlling terminal
See also: https://github.com/pexpect/ptyprocess/issues/34
I observe this on OpenIndiana 151a9 and SmartOS joyent_20160218T022556Z.
Python's os.openpty() method has an unintentional (and undesirable) side-effect. When the parent process itself has no controlling terminal, it acquires the newly allocated pty as its controlling terminal.
The Python implementation goes (error-handling code and conditional compilation elided for clarity):
master_fd = open("/dev/ptmx", O_RDWR | O_NOCTTY); /* open master */ /* change permission of slave */ grantpt(master_fd); /* unlock slave */ unlockpt(master_fd); slave_name = ptsname(master_fd); /* get name of slave */ slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
Running the code under a debugger, the ioctl push of stem causes the parent process to acquire the newly allocated pty as its controlling terminal (when the intent is to gift it to the child, which can not acquire it as it is in a different session).