FreeBSD 12.1: change the default shell for jexec

I want to have different shells in different jails. It looks like there is a bug that prevents that.

How to solve?

1. What if starting jexec with a path to the shell? simple! *even you see you are using bash…. (make an alias)

#jexec 1 /usr/local/bin/bash
#echo $SHELL
/bin/csh

2. What if to set up a default shell by chsh inside a jail

#jexec 1 
#chsh -s /usr/local/bin/bash
#exit
#jexec 1 
#echo $SHELL
/bin/csh

3. What if modify a ~/.profile

SHELL=/usr/local/bin/bash
export SHELL

No. No. No.

Let’s have a closer look what is going on:

By analysing https://github.com/freebsd/freebsd/blob/master/usr.sbin/jexec/jexec.c#L132 you can clearly see that exec shell would be defined if pw_shell is set and if not set it uses default hardcoded /bin/sh ( or /rescure/sh )

setenv("SHELL", *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);

The constant _PATH_BSHELL is defined inside: :https://github.com/freebsd/freebsd/blob/1d6e4247415d264485ee94b59fdbc12e0c566fd0/include/paths.h#L47

#define	_PATH_BSHELL	"/bin/sh"

This gives the idea: You have to have change shell env on the master before starting jexec shell. This is not ideal but let’s test:

#setenv SHELL /usr/local/bin/bash
#jexec 1 
#echo $SHELL
/usr/local/bin/bash

Wow! This is great and works! Lets make it permanently on master:

#chsh -s /usr/local/bin/bash

Yes? Wrong. Such a solution requires you to have installed your favourite shell on master and then inside a jail otherwise you will face this:

#jexec 2
jexec: execlp: /usr/local/bin/bash: No such file or directory

In worst case scenario your default user on master would end up in /bin/sh. You could install missing scripts…

#jexec mycleantestjail
jexec: execlp: /usr/local/bin/fish: No such file or directory
#jexec mycleantestjail pkg install fish -y
#jexec mycleantestjail

The solution script

Even you start shell by aliases like bash or fish – default $SHELL is going to be CSH. This might have implications on other application running inside jails. For example, Midnight Commander has a build-in shell that relay on variable $SHELL. This means when you start mc and then access shell it would be default one ( probably /bin/csh )

The best solution would be to update jexec.c logic to use default $SHELL from a user from inside a jail. C fix possibly should be checking /etc/shells or /etc/pw.conf and not to rely on master default shell. Until then is to modify shell by a script before it gets lunched. It only checks for user root. Any suggestions welcome.

#!/bin/csh
set D=`jexec $1 pw usershow root | awk -F":" '{print $10}'`
set O=`pw usershow root | awk -F":" '{print $10}'`
setenv SHELL ${D}
jexec $*
setenv SHELL ${O}

Save it to jexec2.sh then add to your ~/.cshrc

alias jexec2 ./<path-to-yourfile>/jexec2.sh