== What _/etc/shells_ is and isn't In traditional Unix, _/etc/shells_ has only one true purpose: it lists programs that _chsh_ will let you change your shell to (if it lets you do anything). Before people are tempted to make other programs use this file for something else, it is important to understand the limits of _/etc/shells_. These include but are not limited to: * Logins may have _/etc/passwd_ entries that list other shells. For example, back when restricted shells were popular it was extremely common to not list them in _/etc/shells_ so you couldn't accidentally _chsh_ yourself into a restricted shell and then get stuck. Some but not all programs have used the absence of a shell from _/etc/shells_ as a sign that it is a restricted shell (or not a real shell at all) and they should restrict a user with that shell in some way. Other programs have used different tests, such as matching against specific shell names or name prefixes. (It's traditional for the FTP daemon to refuse access for accounts that do not have a shell that's in _/etc/shells_ and so this is broadly accepted. Other programs are on much thinner ice.) * On the other hand, sometimes you can find restricted shells in _/etc/shells_; a number of systems (Ubuntu and several FreeBSD versions) include _rbash_, the restricted version of Bash, if it's installed. * Not all normal shells used in _/etc/passwd_ or simply installed on the system necessarily appear in _/etc/shells_ for various reasons. In practice there are all sorts of ways for installed shells to fall through the cracks. Of course this makes them hard to use as your login shell (since you can't _chsh_ to them), but this can be worked around in various ways. For example, our Ubuntu systems have _/bin/csh_ and _/bin/ksh_ (and some people use them as their login shells) but neither are in _/etc/shells_. * The (normal and unrestricted) shell someone's actually using isn't necessarily in either _/etc/shells_ or their _/etc/passwd_ entry. Unix is flexible and easily lets you use _$SHELL_ and some dotfile hacking to switch basically everything over to running your own personal choice of shell, per [[my entry on using an alternate shell UsingAlternateShell]]. (Essentially everything on Unix that spawns what is supposed to be your interactive shell has been clubbed into using _$SHELL_, partly because the code to use _$SHELL_ is easier to write than the code to look up someone's _/etc/passwd_ entry to find their official login shell. This feature probably came into Unix with BSD Unix, which was basically the first Unix to have two shells.) * Entries in _/etc/shells_ don't necessarily exist. * Entries in _/etc/shells_ are not necessarily shells. Ubuntu 14.04 lists _screen_. * Not all systems even have an _/etc/shells_. Solaris and derivatives such as Illumos and OmniOS don't. In the face of all of this, most programs should simply use _$SHELL_ and assume that it is what the user wants and/or what the sysadmin wants the user to get. It's essentially safe to assume that _$SHELL_ always exists, because it is part of [[the long-standing standard Unix login environment BecomingAUser]]. As a corollary, a program should not change _$SHELL_ unless it has an *excellent* reason to do so. Note particularly that ~~a user's _$SHELL_ not being listed in _/etc/shells_ means essentially nothing~~. As outlined above, there are any number of non-theoretical ways that this can and does happen on real systems that are out there in the field. As a corollary your program should not do anything special in this case unless it has a really strong reason to do so, generally a security-related reason. Really, you don't even want to look at _/etc/shells_ unless you're _chsh_ or _ftpd_ or _sudo_ or the like. (This entry is sadly brought to you by [[a program getting this wrong https://twitter.com/thatcks/status/555124907630002177]].)