aboutsummaryrefslogtreecommitdiff
path: root/slowbaud.1
blob: 543bb0397c16d18fd1692e10842a54f8a8e582c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
.\" Man page generated from reStructuredText.
.
.TH SLOWBAUD 1 "2021-07-23" "0.0.1" "Urchlay's Useless Stuff"
.SH NAME
slowbaud \- simulate a low bitrate serial connection
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.\" RST source for slowbaud(1) man page. Convert with:
.
.\" rst2man.py slowbaud.rst > slowbaud.1
.
.\" rst2man.py comes from the SBo development/docutils package.
.
.\" Note: if you edit this, run "make" to recreate the man page and README,
.
.\" *then* do a "git commit -a". Even though they're generated files, the man
.
.\" page and README.txt are tracked by git.
.
.SH SYNOPSIS
.sp
\fBslowbaud\fP [\fI<bits\-per\-sec>\fP] [\fI<file>\fP ...]
.sp
\fBslowbaud\fP [\fI<bits\-per\-sec>\fP] \fB\-c\fP [\fI<command>\fP [\fI<arg>\fP ...]]
.sp
\fBslowbaud\fP [\fI<bits\-per\-sec>\fP] \fB\-e\fP \fI<string>\fP [\fI<string>\fP ...]
.sp
\fBslowbaud\fP [\fI<bits\-per\-sec>\fP] \fB\-b\fP [\fI<bytes>\fP]
.SH DESCRIPTION
.sp
slowbaud by default acts as a filter, or like the \fBcat(1)\fP command. It
reads files or its standard input, and writes the contents unmodified
to standard output... but slowly, at the given bits\-per\-second rate.
Input and output are unbuffered.
.sp
slowbaud can also act like \fBecho(1)\fP (the \fB\-e\fP option), or run an
interactive command in a pseudo\-tty (the \fB\-c\fP option).
.sp
The \fI<bits\-per\-sec>\fP argument is optional. If it\(aqs not given, the
bit rate will be set from \fBSLOWBAUD_BPS\fP in the environment, or a
built\-in default of 2400 if that\(aqs not set.
.SH OPTIONS
.INDENT 0.0
.TP
.B \fBbits\-per\-sec\fP
The bit ("baud") rate to simulate. Range is 1 to 500000. This
must be the first argument. slowbaud assumes that if the first
argument is a number, it\(aqs the bit rate. If you\(aqre trying to pass
a filename that consists only of digits, give \fB\-\-\fP as the first
argument, or use e.g. \fI\&./filename\fP\&.
.TP
.B \fB\-e\fP
Echo mode. Prints all further arguments as strings to stdout, separated
by a single space, at the given bit rate. Does not support backslash\-escapes, or any of
the options of the regular \fBecho\fP command. At least one argument is required
after \fB\-e\fP\&.
.TP
.B \fB\-c\fP
Command mode. Next argument (if present) is the command to run, any remaining arguments
become arguments to the command. With no arguments after \fB\-c\fP, a shell is spawned.
This creates a pseudo\-tty, so the command can be interactive.
.TP
.B \fB\-b\fP
Benchmark mode. Prints \fI<bytes>\fP (or 4096, if no \fI<bytes>\fP given) bytes of
zeroes to /dev/null. Mostly useful for development and troubleshooting.
.TP
.B \fB\-h\fP, \fB\-?\fP
Show built\-in help message and exit.
.UNINDENT
.SH ENVIRONMENT
.INDENT 0.0
.TP
.B \fBSLOWBAUD_BPS\fP
Can be used to set the bit rate, when no \fI<bits\-per\-sec>\fP argument is used.
.TP
.B \fBSLOWBAUD_DEBUG\fP
Set this (to any value) in the environment to see verbose debug
output on stderr, including timing accuracy stats.
.TP
.B \fBSHELL\fP
Standard *nix environment variable, used to determine what
shell to run when \fB\-c\fP is given with no \fI<command>\fP\&. If
unset, \fB/bin/sh\fP is used.
.UNINDENT
.SH EXIT STATUS
.sp
Without \fB\-c\fP or \fB\-e\fP, 0 for success, non\-zero on any error such as
nonexistent/unreadable files. slowbaud exits immediately on such
errors (this is unlike \fBcat(1)\fP).
.sp
With \fB\-e\fP, exit status is 0, unless there were no arguments to echo.
.sp
With \fB\-c\fP, exit status is that of the child process, or 127 if
the child process couldn\(aqt be spawned (e.g. command not found).
Of course, the child process could also exit with status 127...
.sp
With \fB\-b\fP, exit status is 0, unless something catastrophic happened
(e.g. unable to open \fB/dev/null\fP for writing).
.SH NOTES
.sp
The timing inaccuracy will almost always result in the bitrate
being slightly too slow.
.sp
We can\(aqt really insert a delay between the bits of a byte, since
I/O is done with byte granularity. For calculation purposes,
\fI<bits\-per\-sec>\fP is divided by 10 to get bytes per second. This
simulates "8\-N\-1": one start bit, 8 data bits, no parity, and 1 stop
bit (total of 10 bits per byte).
.sp
The timing code works by calculating how long to sleep after each
character (in microseconds), but actually sleeping slightly less
than that, then busy\-waiting until the rest of the interval expires.
At slower bitrates, this works well, and the CPU overhead is barely
noticeable (at least on reasonably fast modern systems).
.sp
Timing accuracy depends on your OS, kernel config (HZ and/or NO_HZ
on Linux), and system load. Also on the amount of data, since the
timing loop is self\-regulating (the first few bytes will have less
accurate timing than later ones). No "fancy" techniques like realtime
scheduling or hardware event timers are used. At bitrates up to
115200, on an unloaded Linux system, the timing should be at least
99.9% accurate. At higher bitrates, accuracy will decrease.
.sp
Timing is more accurate on Linux than OSX. It\(aqs done with getitimer()
and sigwait(). This works out to be slightly more accurate than
using usleep() on both Linux and OSX. It would be possible to use
the realtime timer_create() and clock_gettime() API on Linux, for
possibly even better accuracy, but OSX doesn\(aqt have these (and I want to be
portable). On an unloaded OSX system, the accuracy gets steadily worse
as you go above 57600bps. There\(aqs also more CPU overhead on OSX.
.sp
If this were a truly useful application, it would be worth trying to
increase accuracy further, with realtime process scheduling. I didn\(aqt
do this because slowbaud is just a toy, and because the RT stuff tends
to be unportable and require elevated privileges (root, or something
like setrtlimit or extended filesystem attributes to manage capabilities).
.sp
About the name... I\(aqm aware that "baud" is not synonymous with bps. I
just think "slowbaud" sounds better than "slowbps", as a name. Anyway
the stty command on both Linux and OSX misuses the term ("speed
38400 baud"), as well as the man page for termios(3), so I\(aqm in good
company.
.SH BUGS
.sp
With \fB\-c\fP, signals aren\(aqt handled gracefully. Window size changes
(SIGWINCH) don\(aqt get propagated to the child process, and pressing ^C
doesn\(aqt interrupt the process until all pending output is processed.
.SH COPYRIGHT
.sp
slowbaud is copyright 2021, B. Watson <\fI\%yalhcru@gmail.com\fP>. Released
under the WTFPL. See \fI\%http://www.wtfpl.net/txt/copying/\fP for details.
.\" Generated by docutils manpage writer.
.