Date: Mon, 15 Dec 2025 21:34:32 +0000
From: void <[email protected]>
Message-ID: <aUB-6Gynr0XxfC7e@int21h>
| https://www.f451.online/~void/NetBSD/img/rootprompt-example-openbsd.img
| https://www.f451.online/~void/NetBSD/img/rootprompt-example-netbsd10.1.png
For some reason, I seem unable to connect to there, so I have no idea
what (exactly) you want it to look like, or what it does look like,
however...
| The first problem is, when I thought about it was I'm modifying the
| prompt for root and technically maybe I really shouldnt do that.
You can, if you want to, it is your system (I presume) - you can
largely do with it whatever you like (but of course, if you break
things, it is also up to you to fix them). You want root's shell
to be something that only needs the root filesystem mounted however.
| because the sub-problem here is that in order to make the prompt work
| I needed to set it to openbsd's ksh (oksh) shell instead of the default.
I thought OpenBSD used mksh? (nb: I've never used OpenBSD, so that's
just from discussions about shells).
| So I looked at toor account thinking
| I might use that but unlike other BSDs, on Net the toor shell is set
| to /rescue/sh so maybe that shouldn't be modified either.
Not changing that is probably the right thing to do - having /rescue/sh
means that you'd be able to log in if somehow or other you messed up
/bin or /lib or something like that, and no normal programs would be
able to run, the /rescue binary (it is all just one, really) requires
minimal support, a working stdin/stdout and the OS - what's on the rest
of the system doesn't (or shouldn't) matter to it - that way you can get
to a root shell to fix things. But again, if you'd be unlikely to ever
use that method to repair your system (perhaps just reinstalling would be
easier) then again, it is your system, you can change what you like.
You could also just add a third uid==0 username if you want to, so that
one can have a different shell (any shell you like).
| Ultimately what's required is the prompt is red when it's an account
| with elevated privileges.
That we can certainly do in /bin/sh (personally, I prefer to have the
whole window, prompts, output, everything, in a different colour (not red!)
in a root window, but that's just me, I prefer not to have garish colour
changes all over the place).
| I can't find a way to do that (yet) with
| NetBSD's /bin/sh. Is there a way without changing the default shell?
Yes, but:
| [0] I don't know why the host is echoed first either. It looks like this in
| ~/.profile:
| RED="\033[1;37;41m"
| RESET="\033[0;0m"
| export PS1="\n\d \t\n${RED}\u@\h \w ${RESET} # "
it is not much like that at all. First, we're not a csh/ksh/bash descendant,
and don't do \ sequence expanding in prompts at all (no history style !
expansions either).
I'd also suggest that you use tput(1) rather than embedding strings like
the above for RED and RESET - but that part is just for better portability
to other terminals, which might not use vt100 style controls, as long as
the ones you have there are correct, that would be OK.
What you need is documented in sh(1) where it gives this example:
PSlit="$(printf�'\1')"
PS1="${PSlit}$(tput�bold�blink)${PSlit}\$${PSlit}$(tput�sgr0)${PSlit}�"
(these days I'd just do
PSlit=$'\1'
rather than using printf, but that's minor.
That obviously is making a bold blinking '$' as the prompt, but that's OK,
you just change that part to be "red" - and in general, I agree, that
getting the sequences to do that into variables like "RED" and "RESET"
is a better way, rather than running tput several times for each prompt,
on the other hand, running it every time means the prompt automatically
adjust itself, if needed, whenever term changes.
For the escape sequences, just use (outside "" or '') $'\n' for \n
(a newline) - or simply include a literal newline inside quotes, and
sh has variables you can expand for most of the rest of the escape
sequences you're likely to use.
Use ${ToD} instead of '\d \t' (and set ToD_FORMAT to a strftime(3) type
string that says what format you want ${ToD} to expand into, so for
(bash's at least) \d, you'd use
( (as in "Tue Dec 16 06:39:30") - but
you can do whatever you like, including inserting any other text you like.
For \u use either ${EUSER} if the intent is to say "root" in this case,
or ${USER} or ${LOGNAME} if you want your login name (from before su)
to be used instead. For \h use ${HOSTNAME%%.*} - we have nothing that
is exactly \w .. ${PWD#"${HOME}/"} is about as close as we come, but
you can run a $() in PS1 if you want, and whatever it outputs is used
(to do that, currently, though I am considering changing it now we have
a better internal mechanism, you need to have done "set -o promptcmds"
somewhere before setting the using a PS1 value with a command substitution
in it, with that, you can put the output of any command or script into
your prompt).
Instead of the '#' I'd use ${PSc} which is either '#' or '$' depending
upon whether or not you are currently root (uid 0) or someone else.
The only other thing you need to deal with is making sure libedit
(which does the command line editing) doesn't get confused by non-printing
characters in the prompt. That's what setting (and using) ${PSlit} does
(the name is important). When you set PSlit the shell informs libedit
that the character it contains (it needs to be a single, one byte, character)
marks the boundaries of a block of non-printing characters. It needs to be
something which will not otherwise occur anywhere in the prompt (but that's
its only limitation) - that character won't be output as part of the prompt
string. You just put it once before any non-printing (that is, mode
changing) sequence, and again, after it). So, for what you want, at
least approximately (I'm not going to worry about the ${PWD} -> ~ part
for this message) something like (with RED and RESET as you have them, or
set as
RED="$(tput setf 4)" # 4 is red
RESET="$(tput sgr0)"
Then
ToD_FORMAT='%a %b %d %T'
NL=$'\n'
PSlit=$'\1'
PS1='${NL}${ToD}${NL}${PSlit}${RED}${PSlit}${EUSER}@${HOSTNAME%%.*}'
PS1="${PS1}"' ${PWD}${PSlit}${RESET}${PSlit} ${PSc} '
should work (it appears to to me anyway). Note I split that into 2,
to avoid overly long e-mail lines (too hard to read) and it works like
that, but you might prefer it as one long line (without the PS1="${PS1}"
part at the start of the 2nd line there, of course).
Also note you need this to be defined in '' not "" so that the variables
(mostly $ToD and $PWD) aren't expanded until (each time) the prompt is used.
You could optimise it so that the ones that don't ever change are expanded
in the PS1 definition, and the others are deferred for later if you like,
but you'd really never notice the difference.
There's one other issue because of a libedit limitation - the final
character of the prompt cannot be the final ${PSlit} - there must be
at least one more printing character (like a space) after it. In
the above all of the final ' ${PSc} ' are just fine for that purpose.
You'd want to do better than just ${PWD} though - but rather than using
a command substitution (which you could do), I'd tend to do something like
cd() {
command cd "$@" &&
case "${PWD}" in
/) WD=/;;
"${HOME}"*) WD=\~${PWD#"${HOME}"};;
*) WD=${PWD};;
esac
}
and then (after that is defined) execute it once:
cd .
so that WD gets set initially, and then use ${WD} instead of ${PWD}
and allow the cd function to update WD every time it successfully changes
directory (nothing to do for prompts when there has been no cd).
In any case, all of what you want (and more) is possible in /bin/sh
you don't need something bigger, or just different, to achieve it.
(Any NetBSD (from about NetBSD 8 onwards, maybe even 7) can do all of this).
kre