/usr/bin/hexterm is in chiark-scripts 5.0.2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | #!/usr/bin/tclsh8.4
set comment {
#
Use of the screen:
0 1 2 3 4 5 6 7
xxxE hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh_| abcd e_.. .... ...._|
}
# Display:
# | is a vertical delimiter
# E is either | to mean echo is on or ' to mean it is off
# hh are hex digits of output:
# 00-ff actual hex data (bold for stuff we entered)
# 0-f under cursor: one digit entered, need the next
# abcde_.... are ASCII output:
# . things we can't print including SPC and _
# in both, we may see
# space we haven't yet filled
# _ cursor when in other tab
# xxx number of bytes read/written so far
# Keystrokes:
# TAB switch between hex and literal mode
# ^C, ^D quit
# ^Z suspend
# Keystrokes in hex mode only:
# RET move to a new line; if already at start of line,
# set count to 0
# DEL clear any entered hex digit
# SPC send 00
# ' toggle echo
# nyi:
# G-Z record last bytes we transmitted and store in memory
# if we were halfway through a hex byte, first digit
# is length of string to record
# g-z play back memory
# Copyright 2005 Ian Jackson <ian@chiark.greenend.org.uk>
#
# This script and its documentation (if any) are free software; you
# can redistribute it and/or modify them under the terms of the GNU
# General Public License as published by the Free Software Foundation;
# either version 3, or (at your option) any later version.
#
# chiark-named-conf and its manpage are distributed in the hope that
# it will be useful, but WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, consult the Free Software Foundation's
# website at www.fsf.org, or the GNU Project website at www.gnu.org.
if {[llength $argv] != 1} { error "need serial port arg" }
set port [lindex $argv 0]
set count 0
set lit 0 ;# 1 means literal (ASCII) entry mode
set echo 1
proc p {s} {
puts -nonewline $s
}
proc tput {args} {
global tput
if {[catch { set s $tput($args) }]} {
set s [eval exec tput $args]
set tput($args) $s
}
p $s
}
proc csr_pos {lit bytenum} {
set x [expr {
(!$lit ? (3*$bytenum) : 53+$bytenum)
+ ($bytenum>>2) - (2-$lit)*($bytenum==16)
+ 5
}]
tput hpa $x
}
proc csr_this {} { global lit x; csr_pos $lit $x }
proc csr_other {} { global lit x; csr_pos [expr {!$lit}] $x }
proc csrs_erase {} { csr_this; p " "; csr_other; p " " }
proc csr_this_show {} {
global h1
csr_this; if {[info exists h1]} { p $h1; p "\b" }
}
proc csrs_show {} {
csr_other; p _
csr_this_show
}
proc echop {} {
global echo
return [expr {$echo ? "|" : "'"}]
}
proc newline {} {
global x echo count
if {[info exists x]} { csrs_erase; p "\r\n" }
set x 0
p [format "%3x%s%*s|%*s|" $count [echop] 52 "" 21 ""]
csrs_show
}
proc p_ch_spaces {} {
global x lit
if {$x==15} return
if {$lit} { p " " }
if {($x & 3) != 3} return
p " "
}
proc p_rmso {smso} {
if {[string length $smso]} { tput sgr0 }
}
proc ch {d smso} {
global lit x count
if {$x == 16} newline
if {[string length $smso]} { tput $smso }
set h [format %02x [expr {$d & 0xff}]]
set c [format %c [expr {($d > 33 && $d < 127 && $d != 95) ? $d : 46}]]
if {$lit} {
p $c; csr_other; p $h
p_ch_spaces
p_rmso $smso
p _
} else {
p $h; csr_other; p $c
p_ch_spaces
p_rmso $smso
p _
}
incr x
set count [expr {($count+1) & 0xfff}]
csr_this_show
}
proc onreadp {} {
global p
while 1 {
set c [read $p 1]
binary scan $c c* d
if {![llength $d]} {
if {[eof $p]} { error "eof on device" }
return
}
ch $d {}
}
}
proc transmit {d} {
global p echo
puts -nonewline $p [format %c $d]
if {$echo} { ch $d bold }
}
proc k_echo {} {
global echo
set echo [expr {!$echo}]
tput hpa 3
p [echop]
csr_this
}
proc k_newline {} {
global count x
if {$x} {
newline
} else {
set count 0
p "\r"
p [format %3x $count]
csr_this
}
}
proc k_switch {} {
global lit h1
csrs_erase
catch { unset h1 }
set lit [expr {!$lit}]
csrs_show
}
proc k_stop {} {
restore
exit 0
}
proc k_suspend {} {
restore
exec kill -TSTP [info pid]
setup
}
proc k_noparthex {} {
global h1
csrs_erase
catch { unset h1 }
csrs_show
}
proc k_hexdigit {c} {
global h1 echo
if {![info exists h1]} { set h1 $c; p $c; p "\b"; return }
set d [expr 0x${h1}${c}]
unset h1
transmit $d
if {!$echo} { p " \b" }
}
proc onreadk {} {
global lit
while 1 {
set c [read stdin 1]
binary scan $c c* d
if {![llength $d]} {
if {[eof stdin]} { error "eof on stdin" }
return
}
switch -exact $d {
9 { k_switch; continue }
3 - 4 { k_stop; continue }
26 { k_suspend; continue }
}
if {$lit} { transmit $d; continue }
switch -exact $d {
13 { k_newline; continue }
32 { transmit 0; continue }
39 { k_echo; continue }
127 { k_noparthex; continue }
}
if {$d >= 48 && $d <= 57} { k_hexdigit $c; continue }
set kl [expr {$d | 32}]
if {$d >= 97 && $d <= 102} { k_hexdigit $c; continue }
p "\a"
}
}
proc try {script} {
if {[catch { uplevel 1 $script } emsg]} {
catch { puts stderr "(warning: $emsg)" }
}
}
proc tryv {variable script} {
upvar #0 $variable var
if {![info exists var]} return
uplevel 1 "
global $variable
$script
"
unset var
}
proc restore {} {
tryv x { puts "\r\n" }
try { fconfigure stdin -blocking true }
try { fconfigure stdout -blocking true }
tryv term_stty { exec stty $term_stty }
tryv p { close $p }
}
proc setup {} {
global term_stty port p
set term_stty [exec stty -g]
set p [open $port {RDWR NONBLOCK} 0]
exec stty min 1 time 0 -istrip -ocrnl -onlcr -onocr -opost \
-ctlecho -echo -echoe -echok -echonl -iexten -isig \
-icanon -icrnl
exec stty -F $port min 1 time 0 -istrip -ocrnl -onlcr -onocr -opost \
-ctlecho -echo -echoe -echok -echonl -iexten -isig \
-icanon -icrnl \
9600 clocal cread -crtscts -hup -parenb cs8 -cstopb \
-ixoff bs0 cr0 ff0 nl0 -ofill -olcuc
fconfigure $p -blocking false -buffering none -encoding binary \
-translation binary
fconfigure stdin -blocking false -buffering none -translation binary
fconfigure stdout -blocking false -buffering none -translation binary
newline
fileevent stdin readable onreadk
fileevent $p readable onreadp
}
proc bgerror {m} {
try {
restore
global errorInfo errorCode
puts stderr "$m\n$errorCode\n$errorInfo"
}
exit 127
}
if {[catch setup emsg]} {
restore
error $emsg $errorInfo $errorCode
}
vwait quit
|