Initial commit
This commit is contained in:
commit
85b0d6b5ac
3 files changed
+133
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
baud
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
baud - A tool to simulate a specified baud rate in a pipe.
|
||||||
|
|
||||||
|
I wrote this to be able to play some of the old VT100/ansi animations
|
||||||
|
at the rate of your choice. Since most terminal emulator apps render
|
||||||
|
the text as fast as the system can (which is effectively instantaneous),
|
||||||
|
the animations do not actually animate. This allows you to add
|
||||||
|
a throttle to view as if you were on an actual serial terminal.
|
||||||
|
|
||||||
|
It takes one parameter, which is the desired baud rate. If you do not
|
||||||
|
specify one, it will use the default defined below. Extra parameters
|
||||||
|
will be ignored.
|
||||||
|
|
||||||
|
-- Scott Garrett
|
||||||
|
version 2022050401
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define defaultbaudrate 9600
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int baudrate;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if ( argc == 1 )
|
||||||
|
baudrate = defaultbaudrate;
|
||||||
|
else
|
||||||
|
baudrate = atoi(argv[1]);
|
||||||
|
|
||||||
|
/* Cannot have a negative baud rate, and 0 makes no sense
|
||||||
|
(and would cause a division by zero).
|
||||||
|
*/
|
||||||
|
if ( baudrate <= 0 )
|
||||||
|
{
|
||||||
|
printf("Invalid baud rate: %d\n", baudrate);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the desired baud rate into nanoseconds */
|
||||||
|
int baud = 10000000000 / baudrate;
|
||||||
|
|
||||||
|
/* Make sure the final value is in the valid range that nanosleep()
|
||||||
|
supports.
|
||||||
|
*/
|
||||||
|
if ( baud < 0 || baud > 999999999 )
|
||||||
|
{
|
||||||
|
printf("Invalid baud rate: %d\n", baudrate);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now that we know the desired baud rate delay in nanoseconds,
|
||||||
|
load up the struct with the values. 0 seconds and the baud rate delay.
|
||||||
|
*/
|
||||||
|
struct timespec remaining, request = {0, baud};
|
||||||
|
|
||||||
|
while ((c = getchar()) != EOF)
|
||||||
|
{
|
||||||
|
/* Here we grab a character from stdin, write it, flush it out
|
||||||
|
so it is seen immediately, then pause for "remaining" nanoseconds.
|
||||||
|
*/
|
||||||
|
putchar((char)c);
|
||||||
|
fflush(stdout);
|
||||||
|
int response = nanosleep(&request, &remaining);
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+59
@@ -0,0 +1,59 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
Reference in new issue
Block a user