Skip to content

Instantly share code, notes, and snippets.

@juandesant
Forked from jvns/terminal-emulator.py
Last active May 6, 2025 23:23
Show Gist options
  • Select an option

  • Save juandesant/da4661773fee78737583d6928cb434ae to your computer and use it in GitHub Desktop.

Select an option

Save juandesant/da4661773fee78737583d6928cb434ae to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import os, pty, subprocess, time
from pprint import pprint
# Ask the OS to create a new "pseudoterminal pair"
# The shell is going to have the "tty" end and the terminal emulator is going to have the
# "pseudoterminal master" ("ptmx") end
# pprint(os.environ)
ptmx, tty = pty.openpty()
shell_process = subprocess.Popen(
["/bin/bash"],
stdin = tty,
stdout = tty,
stderr = tty,
text = False,
close_fds = True,
# env = {'SHELL': '/bin/zsh', 'HOME': os.path.realpath('.')},
env = os.environ,
)
# send a command to the shell
# (in real life you would wait for the user to type things in and write what they typed in)
commands = [
b"echo \"Hello from $SHELL\"\n",
b"which env\n",
]
def hexdump(byte_stream, encoding='utf-8', grouping=16):
num_bytes = len(byte_stream)
padding = (grouping-num_bytes%grouping)%grouping
byte_stream += bytes(chr(0)*padding, encoding)
def map_byte_to_readable_char(the_byte, valid_range=range(32,128), invalid_char='.'):
return chr(the_byte) if the_byte in valid_range else invalid_char
for row in range(0,len(byte_stream)//grouping):
row_data = [f"{byte_stream[row*grouping+n]:02x}" for n in range(0,grouping)]
row_chars = [
f"{map_byte_to_readable_char(byte_stream[row*grouping+n])}"
for n in range(0,grouping)
]
print(f"{row:06x}: {' '.join(row_data)} {''.join(row_chars)}")
for command in commands:
os.write(ptmx, command)
# wait a bit for the command to execute
time.sleep(0.5)
# read the response and print it out
# (in real life you would implement a GUI and display this to the screen)
response = os.read(ptmx, 1024)
print(f"Received {len(response)} bytes:")
print(hexdump(response,grouping=16))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment