#!/usr/bin/env python3 """pty_baud.py – run a shell behind two baud-rate simulators.""" import os, pty, sys, tty, termios, select, subprocess BAUD = sys.argv[1] if len(sys.argv) > 1 else "baud" SHELL = ["bash", "--norc"] master, slave = pty.openpty() shell = subprocess.Popen(SHELL, stdin=slave, stdout=slave, stderr=slave, preexec_fn=os.setsid, close_fds=True) os.close(slave) baud_out = subprocess.Popen([BAUD], stdin=subprocess.PIPE, stdout=subprocess.PIPE) baud_in = subprocess.Popen([BAUD], stdin=subprocess.PIPE, stdout=subprocess.PIPE) # ── flatten every endpoint to an int fd ────────────────────────── fd_term = sys.stdin.fileno() fd_baud_in_stdin = baud_in.stdin.fileno() fd_baud_in_out = baud_in.stdout.fileno() fd_baud_out_in = baud_out.stdin.fileno() fd_baud_out_out = baud_out.stdout.fileno() # master is already an int from openpty() old = termios.tcgetattr(fd_term) tty.setraw(fd_term) def pump(r, w): try: d = os.read(r, 4096) # r is already an int except OSError: return False if not d: return False try: os.write(w, d) # w is already an int except OSError: return False return True try: while True: r, _, _ = select.select( [fd_term, master, fd_baud_in_out, fd_baud_out_out], [], [], 0.01) if fd_term in r: pump(fd_term, fd_baud_in_stdin) if master in r: pump(master, fd_baud_out_in) if fd_baud_in_out in r: pump(fd_baud_in_out, master) if fd_baud_out_out in r: pump(fd_baud_out_out, fd_term) except KeyboardInterrupt: pass finally: termios.tcsetattr(fd_term, termios.TCSADRAIN, old) for p in (shell, baud_in, baud_out): try: p.terminate() except OSError: pass