1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- """Substitute for the forkpty system call, to support Solaris.
- """
- import os
- import errno
- from pty import (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD)
- def fork_pty():
- '''This implements a substitute for the forkpty system call. This
- should be more portable than the pty.fork() function. Specifically,
- this should work on Solaris.
- Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
- resolve the issue with Python's pty.fork() not supporting Solaris,
- particularly ssh. Based on patch to posixmodule.c authored by Noah
- Spurrier::
- http://mail.python.org/pipermail/python-dev/2003-May/035281.html
- '''
- parent_fd, child_fd = os.openpty()
- if parent_fd < 0 or child_fd < 0:
- raise OSError("os.openpty() failed")
- pid = os.fork()
- if pid == CHILD:
- # Child.
- os.close(parent_fd)
- pty_make_controlling_tty(child_fd)
- os.dup2(child_fd, STDIN_FILENO)
- os.dup2(child_fd, STDOUT_FILENO)
- os.dup2(child_fd, STDERR_FILENO)
- else:
- # Parent.
- os.close(child_fd)
- return pid, parent_fd
- def pty_make_controlling_tty(tty_fd):
- '''This makes the pseudo-terminal the controlling tty. This should be
- more portable than the pty.fork() function. Specifically, this should
- work on Solaris. '''
- child_name = os.ttyname(tty_fd)
- # Disconnect from controlling tty, if any. Raises OSError of ENXIO
- # if there was no controlling tty to begin with, such as when
- # executed by a cron(1) job.
- try:
- fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
- os.close(fd)
- except OSError as err:
- if err.errno != errno.ENXIO:
- raise
- os.setsid()
- # Verify we are disconnected from controlling tty by attempting to open
- # it again. We expect that OSError of ENXIO should always be raised.
- try:
- fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
- os.close(fd)
- raise ExceptionPexpect("OSError of errno.ENXIO should be raised.")
- except OSError as err:
- if err.errno != errno.ENXIO:
- raise
- # Verify we can open child pty.
- fd = os.open(child_name, os.O_RDWR)
- os.close(fd)
- # Verify we now have a controlling tty.
- fd = os.open("/dev/tty", os.O_WRONLY)
- os.close(fd)
|