Take the 2-minute tour ×

For linux machines I can use:

# vi ~/.bashrc # red/green terminal colors regarding exit code

then echo "\\[\\033[0;32m\\]";
else echo "\\[\\033[0;31m\\]";
fi`[\u@\h \w]\[\e[m\] "'
export PS1

to get green terminal when exit code is 0, and get red prompt when exit code is not 0.

How can I do this under OpenBSD? (the default ksh)

(I was trying to do it, but with no luck - using ssh to connect to the OpenBSD machine from my notebook - ubuntu/gnome-terminal. )

share|improve this question
Typically, PS1 does not need to be exported since I don't know of any programs besides interactive shells that use it, and interactive shells get their value of PS1 from the relevant rc file already. The reason I mention this is environment variables take up space in ARG_MAX which means you generally don't want a huge environment, or else you will run into "argument list too long" errors more frequently. –  jw013 May 7 '12 at 1:08
add comment

2 Answers

up vote 2 down vote accepted

The problem is only bash has PROMPT_COMMAND. Try this instead:

PS1='\[$(if (($?)); then tput setaf 1; else tput setaf 2; fi)\]'\
'[\u@\h \w]\['"$(tput sgr0)"'\]'

¹ Caveat: I haven't tested this on ksh, but it avoids PROMPT_COMMAND and works in bash.

² tput uses your system's terminfo databases. This is generally more portable and maintainable than hard-coding escape sequences, provided terminfo is installed correctly.

share|improve this answer
tput: Unknown terminfo capability "2" when I log in via console:P –  LanceBaynes May 7 '12 at 2:31
You need to set TERM to something that supports the setaf attribute, e.g. TERM=xterm. (I think the error indicates tput doesn't know that setaf takes a numeric argument, since it's not set for your current terminal.) –  Mikel May 7 '12 at 3:15
add comment

Each shell has its own way of expanding the prompt. OpenBSD's ksh is pdksh. See its prompt settings in the manual, under the PS1 parameter.

The way ksh works is that it performs parameter substitution, command substitution and arithmetic substitution (all the $ expansions) on the value of PS1 before printing the prompt. So you set PS1 once and for all, but the value is regenerated each time. (You can do that in bash too, if you put shopt -s promptvars in your .bashrc.)

OpenBSD's ksh supports backslash escapes similar to bash. With other versions of ksh, you'd need to translate the bash prompt escape sequences into $ substitutions as well.

PS1='$(if (($? == 0)); then print -n "\\033[32m"; else print -n "\\033[31m"; fi)'
PS1="$PS1"'[\u@\h \w]'$(print '\033')'[0m '

The simple translation above has a few defects:

  • It forks a process each time, to analyze $?. There is a way to avoid this, but it's hackish in ksh88.
  • It causes redrawing bugs, because of the zero-width control sequences. This can be avoided with the gross hack documented in the manual.

Here's some more complex code that uses arithmetic to avoid spawning a subshell and takes care of delimiting non-printable sequences.

escape=$(print '\033')
ctrla=$(print '\001')
PS1=$(print '\001\015')
PS1=$PS1$ctrla$escape'[$(($? ? 31 : 32))m'$ctrla
PS1=$PS1'[\u@\h \w]'
PS1=$PS1$ctrla$escape'[0m'$ctrla' '
share|improve this answer
add comment

Your Answer


