7648 useradd/mod commands operate on /home ... (alternative)

Review Request #420 — Created March 29, 2017 and updated

alp, rm

After Alexander Pyhalov posted https://www.illumos.org/rb/r/286/
I asked for some time to look into an alternative. Here is is.
(Sorry that took so long to finish up.)


1: The header file userdefs.h has a bunch of defines for things
that should not necessarily be constants, but settings that
can be changed by "useradd -D ..." etc.

2: The code to get those settings is currently part of the
"OAM user" commands (usr/src/cmd/oamuser/*) and not in any
library that the various userdefs.h consumers might use.

3: We'd like to have a way to add "vendor" (or distro)
modifications to these defaults, that override the
compiled-in defaults, but not "local" settings.
(Precedence: local, vendor, compiled-in)

4: The useradd defaults are stored in /usr/sadm/defadduser
and /usr/sadm/defaddrole which doesn't work on systems
where /usr is a read-only mount (i.e. some zones).

Proposed solution:

Move the code that reads and writes the "useradd" settings
to a library (libuserdefs), and let programs that need
useradd.h settings link with that library.
(Solves: 1, 2)

Introduce a new location for these settings:
(/etc/default/adduser, /etc/default/addrole)
and use the old locations as "vendor" settings.
The library uses settings (in precedence order)
from: /etc/default/, /usr/sadm/, build-in.
(Solves: 3, 4)

The implementation loadss all the settings at once,
with semantcs that new settings override previous,
and just loads (in order) the built-in values, then
the "vendor" values (if any) and finally the "local".

Upgrade and packaging implications:

Both the the old and new locations used to store the
settings for useradd are currently un-tracked by the
packaging systems. The simplest approach to upgrade
is to let packaging continue to ignore those files.
I'd guess very few people have any /usr/sadm/def*
files, so it would probably be fine to let those
who do have such a file copy it first (by hand).

However, if a distro wants to use a tracked file to
install a "vendor" setting in /usr/sadm/defadduser
(i.e. with defparent=/export/home) then before it
should "migrate" that file before installing: i.e.
If /usr/sadm/defadduser exists and
/etc/default/adduser does not exist,
copy /usr/sadm/defadduser to /etc/default/adduser
It's then safe to replace /usr/sadm/defadduser
with a file tracked by packaging.

Ran the tests added by this change, and useradd etc.

  2. usr/src/cmd/oamuser/user/funcs.c (Diff revision 1)
    These two functions effectively do a nested loop walk of two (small) tables.  They did this before and after this change, but that might not have been obvious.
    To reduce the dependencies to a single "edge" (this code depending on libuserdefs, and not the reverse) I've inverted the inner and outer loops from their previous arrangement.  Other than that, they do the same thing they did before :)
  3. usr/src/cmd/oamuser/user/userdefs.c (Diff revision 1)
    In case it wasn't clear, this big chunk of code simply moved over to libuserdefs : defaults.c
  4. usr/src/cmd/oamuser/user/userdefs.c (Diff revision 1)
    This too, moved to libuserdefs : defaults.c
  5. usr/src/cmd/oamuser/user/userdefs.c (Diff revision 1)
    This too (moved to libuserdefs)
  1. Is libuserdefs.so supposed to be a private interface?

    1. Yes. And userdefs.h (which says so in the top comments).