[TUHS] What's In a Prompt String?

Dan Cross via TUHS tuhs at tuhs.org
Thu Apr 30 00:39:23 AEST 2026


On Tue, Apr 28, 2026 at 10:34 PM Lyndon Nerenberg (VE7TFX/VE6BBM) via
TUHS <tuhs at tuhs.org> wrote:
> For Plan 9's rc(1), on 4th edition (the Bell Labs version), the
> prompt was either 'term% ' or 'cpu% ', depending on which version
> of the kernel you were running.  I forget now what the Labs pre-v4
> systems did.

Not precisely true; the default prompt in `rc` is still '% ' in the source code.

When `rc` starts, it reads `/rc/lib/rcmain`, which (by default)
sources `/usr/$user/lib/profile` (that's the Plan 9 equivalent of
`$HOME/.profile` for Unix folks). By default setting `$prompt` to
either `term%` or `cpu%` is done in the user `lib/profile` that a user
gets by running `/sys/lib/newuser`.

For those that don't know, when you are issued an account on a Plan 9
system, you usually start with an empty home directory. Creating
accounts is a multistep process, including entering the user into the
authentication server's database of active accounts (and optionally
adding them as a user for the `secstore` service), and making them
known to the file server. The latter is done by entering
administrative commands directly to the fileserver (often from the
physical console), and creation of the /usr/$user directory owned by
$user is a side-effect of that part of the process. There is no real
`chown` in normal operation on Plan 9: you could put the file server
in a mode where it allowed you to change ownership of a file, but
anyone could do that, so it was only really meant for initial
installation or similar maintenance. Thus, the user initializes their
environment the first time they log in by running `/sys/lib/newuser`.
That's a script that sets up your home directory, including creating
your personal `bin` directories and shell profile, creates your mail
spool file, and so on, and eventually starts the window system.

9front did change the default `lib/profile` installed by `newuser` to
set `$prompt` to include `$sysname` if running on a CPU server,
though. The effect is certainly exactly what you described, just the
mechanism is a bit different.

> 9front changed the prompt to 'hostname% ' pretty early on. ('hostname'
> was set to the value in /dev/hostname.)  Makes it easier to track
> which host you are cpu'd into.

Looks like they still do that in the default `lib/profile`.

> Either way, once the prompt is set (e.g. foo%). a function of the
> same name is defined as a noop, allowing you to snarf-n-barf
> blocks of commands from the terminal buffer with the prompt
> becoming invisible to the shell.

Yeah, that's kind of nifty.

It's just a shell function that evaluates to the function's arguments:
e.g., the plan9 one for a CPU server is just `fn cpu%{ $x^* }`.

The syntax here may be somewhat unfamiliar to most TUHS readers: in
`rc`, the `^` operator joins strings, and in this context, `$x` is set
to the string '$'.  Hence, `$x^* ` evaluates to `$*`, which in turn
expands to a list of strings (this is different than the Bourne shell
where `$*` evaluates to the string, "$1 $2 ...") that are the
arguments to the function. The upshot is that this causes the shell to
invoke the command (the first argument to the `cpu%` function) with
the remainder of the arguments as the command's arguments.  An
exercise for the reader is to figure out how this subterfuge with
string concatenation is different than just having `$*` directly in
the body of the function; it's a neat trick once you see how it works
and why.

> I did the equivalent by wrapping my prompt between ':' and ';'.
> E.g.
>
>         : lyndon at gamma:/usr/lyndon;
>
> This let me achive the same snarf-n-barfablilty without having to
> create and delete noop functions every time I changed the directory.
> (I've been doing this on Unix for ages, too.)

Same, but I just put the hostname into the prompt.

Byron Rakitzis wrote an independent implementation of `rc` that
defaulted the prompt to `;` for precisely this (I suspect that is what
Edouard Klein was referring to with the manpage excerpt posted earlier
in the thread). "Byron's shell" was pretty popular before Russ Cox did
the heavy lifting to liberate the plan9 commands from Plan 9 itself
with his "plan9port".

Incidentally, Rakitzis's shell also replaced one of the gnarlier
syntactic oddities of `rc`: for obscure grammatical reasons, the `if`
statement for conditionals does not have a corresponding `else`;
instead, there is an `if not` that serves the same purpose (Duff calls
this a "two-tailed conditional" in the `rc` paper). For some reason I
thought that 9front made a similar change in their version, but I
don't see it now.

        - Dan C.


More information about the TUHS mailing list