Wandering Thoughts archives

2008-08-15

Using a non-standard shell as your login shell

Suppose that you want to use a non-standard shell as your login shell (for the purposes of this, 'non-standard' means that it's not installed system-wide; you have to compile your own version). Further suppose, for the sake of argument, that the shell you want to use doesn't have a command-line option to tell it to be a login shell.

If your shell did have such a command line option, using it as your login shell would be simple. Set your system shell to /bin/sh and then have a .profile that just said something like:

SHELL=$HOME/bin/shell; export SHELL
exec $SHELL --login

(This doesn't work on some systems in some circumstances, but that's another entry entirely.)

Without such an option, you need some way to make your non-standard shell think that it is being run as a login shell by login (and things that imitate it, like your SSH daemon). As you might guess, there is a long-standing convention for how login communicates this to the shell: a login shell has a '-' as the first character of its program name.

(This works because the entire argument list, including the program name (aka 'argument zero'), is entirely up to the program that runs you; it need not have anything to do with your actual file name.)

This really means the first character, which means that you need some way to make the first character be a '-'. As it happens, most or all shells just use the bare program name if you run something that is found in your $PATH. So what you need is two-fold: first, you need a version of your shell that's called '-shell' (easily gotten with a symlink or a hardlink), and second, you need to add $HOME/bin to your $PATH so you can run your shell without an absolute or relative path.

This gives you the magic incantation:

SHELL=$HOME/bin/shell
PATH=$HOME/bin:$PATH
export SHELL PATH
exec -shell

(Then you run into a bash irritation.)

UsingAlternateShell written at 00:33:32; Add Comment

2008-08-14

A bash irritation: the incompatible exec

There are a reasonable number of good things about bash (and the general GNU program attitude of which it is a standards-bearer). But every so often it does something that causes me to grind my teeth. This time around the irritation is what bash has done to the innocent exec command.

What they've done is simple: they've made exec take options.

The easiest way to explain the problem with this is in illustrated form. So:

sh$ exec -rc
<... program runs ...>

bash$ exec -rc
bash: exec: -r: invalid option
exec: usage: exec [-cl] [-a name] file [redirection ...]
bash$ exec -- -rc
<... program runs ...>

sh$ exec -- -rc
exec: --: not found

Oops.

Since bash's exec takes options, it must complain about invalid options. This makes it reject valid programs that happen to start with a dash, so it needs a way around that, but the way is not compatible with other Bourne shells because, of course, exec does not take options so there is no need to support an option to ignore things that look like options.

(As a bonus irritation bash does this all the time, not just when invoked as bash. So much for compatibility.)

If you are in this situation, it may be helpful to know that one way of checking to see if you are in bash is to look for the presence of a $BASH_VERSINFO environment variable. There are probably better ways, but this one works well enough for me and I could spot it in the bash manpage.

(I stubbed my toe on this today because Ubuntu 8.04 changed /bin/sh from bash to another, more strictly Bourne compatible shell, which made my previous slapdash workaround stop working so I had to actually pay attention to this issue.)

BashExecAnnoyance written at 00:57:10; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.