syst: the terminal · sysk 044

syst

sysk describes; whatever shows it lays out. The shell says what its answers are: text, a value, or a word of its own such as the prompt. The terminal carries them. A host on the person's machine draws them: a run of records as a table, at the width the person's terminal really has. On a plain serial line nothing changes, so sysk is never unreadable.

Three places, one job each

Unix puts a tty between a program and the person: a line discipline in the kernel that echoes, edits and turns Ctrl-C into a signal, with escape codes for anything more. sysk's terminal does almost none of that (sysk 015): the person's end edits the line and sends it whole. syst takes the next step. Programs no longer format for a screen at all. The shell knows what each answer is, the terminal task carries it, and the host decides how it looks.

The shell and the terminal run in sysk, on the RISC-V machine; the host runs on the person's machine, at the other end of the serial line: tools/attach.rkt, which make run starts. Select a box.

What the shell says

An answer is a line of 64 bytes, as since sysk 013: byte 0 is the length of the text that follows. The length is below 64, so its six bits leave two over, and since sysk 044 they say what the text is. The shell's say sets them: a line that is exactly one s-expression is a value (sx-one), anything else is text. The prompt and the region numbers are the shell's own, control. A value longer than a line goes in pieces that the next answer continues, so a value is always whole by the time anything shows it.

KindBitsTextShown on a plain lineSent to a host
text00any lineas it is(text "…"), quoted
value01one s-expression, or its last piecewrapped between its fields(out VALUE)
more11a piece of a value; the next answer goes onheld until the value is wholeheld until the value is whole
control10(prompt "sysk> "), (region 3)the prompt, unfinished; regions not at allas it is

Nothing a program prints can pass for the shell. The kind is in byte 0, never in the text. A job's lines are clamped to text when the shell relays them, and a file that holds (region 9) is said as a value, so a host receives (out (region 9)): data, never control. The same rule will carry the trusted path later (docs/authority.md): only the terminal task can write outside these messages.

On the wire

A host says (syst 1) as its first line. The terminal answers it and from then on writes one message a line, and reads one: what the person types comes as (line "…"), in pieces of at most 63 bytes as a plain line longer than a message is, and the end of input as (eof). Before that, or with no host at all, the terminal shows everything as it always has. One session, both ways: the person types cat /sys/task/*/status, then uptime (abridged to four of the ten tasks).

on the serial line

what the person sees

What the person types is shown by their own terminal, not sent back by sysk. The messages are what the boot tests check (tests/boot-test.rkt); the layout is a function of the messages alone, tested without a machine (tests/syst-test.rkt).

Values, a *, and where

Three small things in the shell make values worth having. cat says a whole line that is one s-expression as one value, however long. A path may have one component that is *: cat /sys/task/*/status is cat of each task's status, in the directory's order. And where keeps the values that have a field: (where (state live) (cat /sys/task/*/status)). Each is the shell's, because each is about what a command means; none knows how anything looks.

sysk> (where (from terminal) (cat /sys/chan/*))
name    bytes  depth  queued  ended  from      to
screen  64     2      0       no     terminal  uart-driver
lines   64     1      0       no     terminal  sugar

where filters what cat shows, for now: around anything else it says so. A path with a * is made in the job table's buffer, free while a file is shown, and the directory is read again for each name, since showing a file uses the reply buffers; a directory of 64 names at most.

The host

tools/syst.rkt is the layout, and tools/attach.rkt the relay that uses it: QEMU's serial line on one side, the person's terminal on the other. It holds a run of values in one region. When the run ends (text, a prompt, another region, a value of another shape), it is laid out: two or more records with the same head and keys, each field an atom, are a table if it fits the terminal's width; anything else is written as it is, wrapped between fields, and inside a string between words, so a long string is never cut (sysk 057). A line from a region older than the newest, a job in the background, carries that region's number. make run speaks syst; tools/attach.rkt --plain relays the bytes as before; --pt hands the line to postterm's pt-attach.

Tab

At a terminal the host edits the line itself (sysk 050): sysk never edits, and the canonical mode of a terminal cannot see a Tab. On Tab, while sysk waits for a line, it sends (complete WORD ...), the line so far as words, and takes the shell's choices out of what comes back before the next prompt, without showing them as output. One choice is filled in whole; several fill in what they share; when they share nothing more, they are shown in columns under the line, and the line comes back. Inside (where (FIELD VALUE) ...) the host does not ask: a value describes itself, so the records it last laid out are the fields there are and their values, and Tab offers those (sysk 051): cat /sys/task/*/status, then (where (st⇥ is (where (state , and l⇥ is live. Up and down walk the lines typed before; Ctrl-U empties the line. Lines a job prints in the background come above the line being typed, which is drawn again under them. With --plain, or with no terminal, the host edits nothing, as before.

sysk> cat /sys/task/s⇥
/sys/task/sugar/   /sys/task/shell/   /sys/task/slot-0/
/sys/task/slot-1/  /sys/task/slot-2/  /sys/task/slot-3/
sysk> cat /sys/task/sl⇥
sysk> cat /sys/task/slot-
sysk> follow /log --q⇥
sysk> follow /log --quiet 

The choices are values the shell said, (choice (word /sys/task/sugar/) (kind dir)); their words are what the host shows. What a program accepts and what Tab offers come from one place, the catalogue the job check judges by.

Not yet: watch laid out in place, a region drawn again whenever what it shows changes (the shell's watch, sysk 049, says each change as a new value today); results kept as files, /res/3; a line only the terminal task may write, for the trusted path; and postterm as a host, through the upgrade its line form designs.