Close a PseudoTTY created via pty.openpty()
You can use os.close to close master and slave.
os.close(fd) Close file descriptor fd.
Note This function is intended for low-level I/O and must be applied
to a file descriptor as returned by os.open() or pipe(). To close a
“file object” returned by the built-in function open() or by popen()
or fdopen(), use its close() method.
OSError: [Errno 24] when multithreading pwntools
It turns out pwntools process API does not close stderr or stdout, so closing them before returning from run, solves the problem.
How to connect INET socket to PTY device in Python
This can be done using select.poll() instead of select.select(), because select.poll() will work with both File Descriptors and Sockets.
def sockToPty(clisock,addr):
(master, slave) = os.openpty()
tty.setraw(master, termios.TCSANOW)
print('PTY: Opened {} for {}'.format(os.ttyname(slave), addr))
mypoll = select.poll()
mypoll.register(clisock, select.POLLIN)
mypoll.register(master, select.POLLIN)
try:
while True:
fdlist = mypoll.poll(1000)
for fd,event in fdlist:
# We treat sockets and FDs differently
if fd == master:
data = os.read(fd, 4096)
if len(data) == 0:
print('PTY: {}, {} exiting due to Zero read.'.format(addr, os.ttyname(slave)))
raise GetOut
clisock.send(data)
else:
data = clisock.recv(4096)
if len(data) == 0:
print('PTY: {}, {} exiting due to Zero read.'.format(addr, os.ttyname(slave)))
raise GetOut
os.write(master, data)
except GetOut:
os.close(master)
os.close(slave)
clisock.shutdown(socket.SHUT_RDWR)
clisock.close()
This code is more complex than it needs to be for simple sockets - with a TCP socket, you can simply use the fileno() for that socket as a File Descriptor and then you treat both sides the same way (os.read(), os.write()). However, if you're going to use this with an SSLSocket, you need the more complicated version above, because if you grab the fileno() from an SSLSocket it expects you're going to handle the TLS layer as well as the data.
pty multiplexer
In the end I wrote a simple TCP server, just like I said I didn't want to... It works really well though. It uses the same general architecture as the code on the question but with TCP sockets instead of pseudo terminals.
I posted it here in case anyone wants to use it.
To call it:
md:mux_serial> ./mux_server.py --device /dev/ttyS0 --baud 115200 --port 23200
MUX > Serial port: /dev/ttyS0 @ 115200
MUX > Server: localhost:23200
I'm using socat
on another terminal to access the port directly...
md:~> socat -,raw,echo=0,escape=0x0f TCP4:localhost:23200
...or to create a pseudo terminal to use inside scripts that require those:
md:~> socat -d -d pty,raw,echo=0 TCP4:localhost:23200
2012/10/01 13:08:21 socat[3798] N PTY is /dev/pts/4
2012/10/01 13:08:21 socat[3798] N opening connection to AF=2 127.0.0.1:23200
2012/10/01 13:08:21 socat[3798] N successfully connected from local address AF=2 127.0.0.1:35138
2012/10/01 13:08:21 socat[3798] N starting data transfer loop with FDs [3,3] and [5,5]
Related Topics
Cannot "Pip Install Cryptography" in Docker Alpine Linux 3.3 with Openssl 1.0.2G and Python 2.7
Ctypes Loading a C Shared Library That Has Dependencies
How to Find the Target File's Full(Absolute Path) of the Symbolic Link or Soft Link in Python
How to Rewrite Output in Terminal
What Is the Return Value of Subprocess.Call()
Package Libffi Was Not Found in the Pkg-Config Search Path Redhat6.5
What Is My Current Desktop Environment
Django Form Dropdown List of Numbers
How to Run Python Script on Terminal (Ubuntu)
Multiprocessing.Pool Spawning New Childern After Terminate() on Linux/Python2.7
Python Error - "Importerror: Cannot Import Name 'Dist'"
How to Get the Python Call Stack with the Linux Perf
No Schema Has Been Selected to Create in ... Error
Letsencrypt Importerror: No Module Named Interface on Amazon Linux While Renewing
Install Tkinter on Amazon Linux
Why Does Python "Preemptively" Hang When Trying to Calculate a Very Large Number