def launch_proc_with_pty(args, stdin=None, stdout=None, stderr=None, echo=True):
"""Similar to pty.fork, but handle stdin/stdout according to parameters
instead of connecting to the pty
:return tuple (subprocess.Popen, pty_master)
"""
def set_ctty(ctty_fd, master_fd):
'''Set controlling terminal'''
os.setsid()
os.close(master_fd)
fcntl.ioctl(ctty_fd, termios.TIOCSCTTY, 0)
if not echo:
termios_p = termios.tcgetattr(ctty_fd)
# termios_p.c_lflags
termios_p[3] &= ~termios.ECHO
termios.tcsetattr(ctty_fd, termios.TCSANOW, termios_p)
(pty_master, pty_slave) = os.openpty()
p = subprocess.Popen(args, stdin=stdin, stdout=stdout,
stderr=stderr,
preexec_fn=lambda: set_ctty(pty_slave, pty_master))
os.close(pty_slave)
return p, open(pty_master, 'wb+', buffering=0)
python类TIOCSCTTY的实例源码
def prepare():
os.setsid()
fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0)
def prepare():
os.setsid()
fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0)
def _setup_slave_pty(self):
"""Set suitable tty options for our pty slave
"""
os.setsid()
fcntl.ioctl(self.slave, termios.TIOCSCTTY, 0)
os.close(self.master)
os.dup2(self.slave, STDIN)
os.dup2(self.slave, STDOUT)
os.dup2(self.slave, STDERR) # FIXME can we handle stderr better?
os.close(self.slave)
def _setupChild(self, masterfd, slavefd):
"""
Set up child process after C{fork()} but before C{exec()}.
This involves:
- closing C{masterfd}, since it is not used in the subprocess
- creating a new session with C{os.setsid}
- changing the controlling terminal of the process (and the new
session) to point at C{slavefd}
- duplicating C{slavefd} to standard input, output, and error
- closing all other open file descriptors (according to
L{_listOpenFDs})
- re-setting all signal handlers to C{SIG_DFL}
@param masterfd: The master end of a PTY file descriptors opened with
C{openpty}.
@type masterfd: L{int}
@param slavefd: The slave end of a PTY opened with C{openpty}.
@type slavefd: L{int}
"""
os.close(masterfd)
os.setsid()
fcntl.ioctl(slavefd, termios.TIOCSCTTY, '')
for fd in range(3):
if fd != slavefd:
os.close(fd)
os.dup2(slavefd, 0) # stdin
os.dup2(slavefd, 1) # stdout
os.dup2(slavefd, 2) # stderr
for fd in _listOpenFDs():
if fd > 2:
try:
os.close(fd)
except:
pass
self._resetSignalDisposition()