[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

What are desired semantics for /etc/shells?



Hi,

Due to working on installation bootstrap, I was looking into
`/etc/shells`.

Introduction
============

`/etc/shells` contains valid login shells. Some programs match the configured
shell of a user against this file to check whether a user is a normal user or a
system users. For details on this file refer to `man 5 shells`. On Debian
systems, it can be managed using the commands `add-shell` and `remove-shell`
both of which are part of `debianutils`.

Inconsistency
=============

Some maintainer scripts take care to only run `add-shell` for initial
configuration or for upgrading from an ancient version that didn't call
`add-shell`. Others call `add-shell` for every invocation of `postinst`.
Packages that only call `add-shell` once:
 * `bash`
 * `bash-static`
 * `dash`
 * `sash`
 * `tmux`
Packages that only call `add-shell` during `postinst configure`:
 * `csh`
 * `elvish`
 * `mksh`
 * `screen`
 * `tcsh`
Packages that call `add-shell` during any `postinst` invocation:
 * `9base`
 * `fish`
 * `ksh`
 * `myrescueshell`
 * `rc`
 * `xonsh`
 * `yash`
 * `zsh`
 * `zsh-static`

In practice, all of the packages will add their shells on initial
configuration. The second and third category will also add their shell on
package upgrades. Arguably, doing so violates Debian policy section 10.7.3,
which says that package upgrades must preserve local changes (such as removing
a shell) on upgrades.

Desired behaviour
=================

This raises the question of what the desired semantics for `/etc/shells` are.
Do we want the strict interpretation of the policy to be followed and update
all those packages to conditionalize their `add-shell` invocations? Or is
`/etc/shells` a simple collection of installed shells and administrators are
not supposed to mess with it? The latter interpretation somewhat conflicts with
our policy, so we might have to update it. If `/etc/shells` is not to be messed
with, maybe it should not live inside `/etc`?

Declarative packaging
=====================

Editing `/etc/shells` by running a command during a maintainer script is less
than ideal when it comes to declarative packaging. The goal of declarative
packaging is to make reasoning about packages easier by eliminating the need
for maintainer scripts as much as possible. One solution for this case could be
`dpkg-trigger`. All the shell-providing packages could drop a snippet into a
particular directory and `debianutils` could concatenate them into
`/etc/shells`. Doing so would delete quite a number of maintainer scripts and
centralize the chance for introducing bugs and inconsistencies such as the ones
above into one maintainer script.

I think using triggers has an obvious benefit here, but depending in the
intended semantics of `/etc/shells`, implementing the part about preserving
user changes may be difficult. A possible solution could be moving
`/etc/shells` to `/var` and replacing it with a symbolic link when its contents
match with the generated one one.

For the installation bootstrap, the trigger-based solution would make any
ordering issues related to `/etc/shells` fully go away. That would be quite an
improvement.

Helmut


Reply to: