Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/ptyprocess/_fork_pty.py: 5%
37 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1"""Substitute for the forkpty system call, to support Solaris.
2"""
3import os
4import errno
6from pty import (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD)
7from .util import PtyProcessError
9def fork_pty():
10 '''This implements a substitute for the forkpty system call. This
11 should be more portable than the pty.fork() function. Specifically,
12 this should work on Solaris.
14 Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
15 resolve the issue with Python's pty.fork() not supporting Solaris,
16 particularly ssh. Based on patch to posixmodule.c authored by Noah
17 Spurrier::
19 http://mail.python.org/pipermail/python-dev/2003-May/035281.html
21 '''
23 parent_fd, child_fd = os.openpty()
24 if parent_fd < 0 or child_fd < 0:
25 raise OSError("os.openpty() failed")
27 pid = os.fork()
28 if pid == CHILD:
29 # Child.
30 os.close(parent_fd)
31 pty_make_controlling_tty(child_fd)
33 os.dup2(child_fd, STDIN_FILENO)
34 os.dup2(child_fd, STDOUT_FILENO)
35 os.dup2(child_fd, STDERR_FILENO)
37 else:
38 # Parent.
39 os.close(child_fd)
41 return pid, parent_fd
43def pty_make_controlling_tty(tty_fd):
44 '''This makes the pseudo-terminal the controlling tty. This should be
45 more portable than the pty.fork() function. Specifically, this should
46 work on Solaris. '''
48 child_name = os.ttyname(tty_fd)
50 # Disconnect from controlling tty, if any. Raises OSError of ENXIO
51 # if there was no controlling tty to begin with, such as when
52 # executed by a cron(1) job.
53 try:
54 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
55 os.close(fd)
56 except OSError as err:
57 if err.errno != errno.ENXIO:
58 raise
60 os.setsid()
62 # Verify we are disconnected from controlling tty by attempting to open
63 # it again. We expect that OSError of ENXIO should always be raised.
64 try:
65 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
66 os.close(fd)
67 raise PtyProcessError("OSError of errno.ENXIO should be raised.")
68 except OSError as err:
69 if err.errno != errno.ENXIO:
70 raise
72 # Verify we can open child pty.
73 fd = os.open(child_name, os.O_RDWR)
74 os.close(fd)
76 # Verify we now have a controlling tty.
77 fd = os.open("/dev/tty", os.O_WRONLY)
78 os.close(fd)