absd-sh(1)
MILESTONE-QUALIFIED
Rendered from the page's mdoc source at milestone/general-usability-qemu-20260927 (platform ff025b1)
with GNU groff version 1.23.0, using the same command the image build uses; an ABSD session running
man 1 absd-sh prints this text. It is dated 2026-09-27; the build commands and
repository files it mentions are in private sources, and later work is not in it.
All pages.
ABSD-SH(1) General Commands Manual ABSD-SH(1) NAME absd-sh -- the ABSD command shell SYNOPSIS absd-sh [-c line] DESCRIPTION absd-sh reads one line at a time and runs it as one pipeline. Without arguments it writes the prompt `absd$ ' before every line, and at the end of its input exits with the status of the last line. With -c it runs line and exits with its status. It is the shell an interactive SSH session starts. It is deliberately small: it is not a POSIX shell and does not run scripts. A command given to ssh (`ssh host ls /bin') does not run under absd-sh: the SSH server splits it at whitespace, with no quoting, pipes, or redirection, and runs its first word directly (a bare name as /bin/name). To run a pipeline without a terminal, write the lines to the shell's standard input: `echo 'ls /bin | wc -l' | ssh host'. Words A line splits into words at whitespace. Double quotes group: `"a b"' is one word, and `a"b c"' is the word `ab c'. Inside quotes, `\"' and `\\' stand for `"' and `\', and `|', `<', `>' are ordinary characters. Outside quotes a backslash is an ordinary character. Nothing else is special: `$', `*', `~', `;', `&', and `#' are ordinary characters, so there are no variables, no globbing, no command lists, and no comments. An unterminated quote is a syntax error. Commands The first word names the command. The builtins are listed below. Any other name runs a program from the filesystem: the word itself when it contains a `/', resolved against the working directory, otherwise /bin/name. There is no PATH search. A program is a static ABSD executable; there is no `#!' and no execute permission. The remaining words are its arguments. It starts with the shell's working directory and environment, and with any of its three standard streams that is not piped or redirected shared with the shell. Pipelines and redirection Commands joined by `|' run at the same time, each one's standard output feeding the next one's standard input through a kernel pipe. When a reader ends first, the writer's next write fails with a broken pipe error; there is no signal. A pipeline's status is its last command's. Each command may redirect its streams: < file standard input from file > file standard output to file, created or truncated >> file standard output appended to file 2> file standard error to file 2>> file standard error appended to file The shell opens every redirection itself, with its own authority, before anything starts; if one cannot be opened nothing starts and the status is 1. The command never holds the file: its stream is a pipe, and the shell copies between the pipe and the file. These are syntax errors (status 2, nothing starts): an empty command in a pipeline, a redirection without a file name, the same stream redirected twice, output both to a file and into a pipe, input both from a file and from a pipe, and descriptor duplication such as `2>&1'. Narrowing a command's authority By default a started command gets the shell's filesystem authority: a file server channel bound to the shell's own mounts, never more. Two prefixes narrow it for one command: ro command ... the same mounts, all read-only nofs command ... no filesystem at all A command started this way still writes its standard output and error; `ro cmd > file' writes file through the shell, while cmd itself cannot write anywhere. The prefixes apply to programs, not to builtins. Each command needs a file server channel of its own: one of the shell's spare channels (at most two, fewer while other sessions are open), or, for one command at a time, the shell's own channel lent to it. ro and nofs need a spare, and so does every command while the shell is copying a redirection. A command that gets no channel is not started (status 126). See "CAVEATS". Builtins cd [dir] Change the working directory to dir, which must be an existing directory the session can see; without dir, to /. pwd Print the working directory. echo [word ...] Print the words separated by single spaces. status Print the status of the last line. exit [n] Exit with status n, or with the last status. ps List this session's processes; see ps(1). shutdown [-h | -p | -r now] Ask sshd to halt the machine, or with -r to restart it; see shutdown(8). reboot Ask sshd to restart the machine; see reboot(8). ps, shutdown, and reboot are requests to the SSH server on the session's control channel, which only a shell sshd started for an interactive session holds; any other absd-sh answers `no session control channel' with status 1. pwd, echo, status, and ps may start a pipeline (the shell writes their output into the next command) and may take >, >>, and 2>. cd, exit, shutdown, and reboot cannot be part of a pipeline. Diagnostics and status When the last command of a line exits with a nonzero status the shell reports `absd-sh: name: exit status n'. The statuses the shell itself assigns: 1 a redirection could not be opened or completed 2 a syntax error, or a builtin used wrongly 126 the program was found but could not be started 127 the program was not found 128 the program ended without an exit status (it faulted or was killed) 130 the line was interrupted with ^C (nothing more is printed) On a terminal With a terminal (`ssh -t'), or plain `ssh host', the SSH server, not the shell, echoes and edits the line: DEL or BS erases a character, ^U the line, and ^C discards the line being typed. ^C while a line runs interrupts it. The key never reaches the command's input: the SSH server tells the shell on the session's control channel, and the shell kills every command of the running pipeline with the process handle it holds, waits for them, and prompts again; the line's status is 130. What a command wrote to a redirection file before it was killed stays there. The shell looks for ^C between bounded waits on its commands, so it acts within a few milliseconds of the SSH server passing it on. A ^C typed at the prompt only discards the line; it does not interrupt the next command. A line holds at most 4095 bytes. ^D on an empty line ends input for the whole session: a command reading standard input sees end of file, and so does the shell, which then exits. Standard output and standard error arrive on the one screen, in the order written. The terminal type and window size are not used. EXAMPLES absd$ cat /etc/motd | wc -l 1 absd$ ls /home/operator > /home/operator/listing absd$ ro cp /etc/motd /home/operator/copy cp: /etc/motd -> /home/operator/copy: ABSD filesystem is mounted read-only absd-sh: cp: exit status 1 absd$ nofs df df: this process has no file server channel (-2) absd-sh: df: exit status 1 SEE ALSO intro(1), ps(1), filesystem(7), handles(7), process(7), reboot(8), shutdown(8) CAVEATS ^C ends the commands the shell started, not what they started in turn: there is no process-tree kill. A command that itself started programs (another absd-sh, for instance) leaves them running when it is interrupted; they are adopted by init, keep the session's input, output, and filesystem channel until they end, and may take lines typed at the prompt. ps(1) counts them. Without a terminal (`ssh -T') there is no ^C. Ending the SSH connection ends the shell; its running commands lose their standard streams and their filesystem authority, and run to their own end. How many commands of one pipeline can hold a file server channel at once depends on how many sessions are open; there is no fixed number to rely on beyond two. Standard input is shared with the shell, but lines the shell has already read are not visible to a command. BUGS There are no globbing, variables, command lists (`;' and `&&'), descriptor duplication, job control, here-documents, or scripts. ABSD September 27, 2026 ABSD-SH(1)