Merge branch 'vendor/OPENRESOLV'
[dragonfly.git] / tools / pw-update.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2020 The DragonFly Project.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # 1. Redistributions of source code must retain the above copyright
11 #    notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 #    notice, this list of conditions and the following disclaimer in
14 #    the documentation and/or other materials provided with the
15 #    distribution.
16 # 3. Neither the name of The DragonFly Project nor the names of its
17 #    contributors may be used to endorse or promote products derived
18 #    from this software without specific, prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
24 # COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 # SUCH DAMAGE.
32 #
33
34 # Exit if any untested command fails in non-interactive mode
35 set -e
36 # Exit when an undefined variable is referenced
37 set -u
38
39 # usage: add_users <etcdir> <master.passwd> <group>
40 #
41 # Add new users and groups in <etcdir> according to the given <master.passwd>
42 # and <group> files.
43 #
44 # NOTE: Existing users and groups are not modified.
45 #
46 # NOTE: There is circular dependence: 'groupadd' requires the members
47 #       already exist, while 'useradd' requires the group exists.
48 #       So first assign new users to the 'nogroup' group, and then make
49 #       adjustments after group creation.
50 #
51 add_users() {
52         local etcdir="$1"
53         local fpasswd="$2"
54         local fgroup="$3"
55         local _name _pw _uid _gid _gids item
56         local _class _change _expire _gecos _home _shell _members
57
58         echo "===> Adding new users ..."
59         _gids=""
60         while IFS=':' read -r _name _pw _uid _gid _class \
61                         _change _expire _gecos _home _shell; do
62                 case ${_name} in
63                 '' | \#*) continue ;;
64                 esac
65                 if pw -V ${etcdir} usershow ${_name} -q >/dev/null; then
66                         continue
67                 fi
68                 echo "   * ${_name}: ${_uid}, ${_gid}, ${_gecos}, ${_home}, ${_shell}"
69                 # Assign to the 'nogroup' group, and then adjust later.
70                 pw -V ${etcdir} useradd ${_name} \
71                         -u ${_uid} \
72                         -g nogroup \
73                         -d ${_home} \
74                         -s ${_shell} \
75                         -L "${_class}" \
76                         -c "${_gecos}"
77                 _gids="${_gids} ${_name}:${_gid}"
78         done < ${fpasswd}
79
80         echo "===> Adding new groups ..."
81         while IFS=':' read -r _name _pw _gid _members; do
82                 case ${_name} in
83                 '' | \#*) continue ;;
84                 esac
85                 if pw -V ${etcdir} groupshow ${_name} -q >/dev/null; then
86                         continue
87                 fi
88                 echo "   * ${_name}: ${_gid}, ${_members}"
89                 pw -V ${etcdir} groupadd ${_name} -g ${_gid} -M "${_members}"
90         done < ${fgroup}
91
92         echo "===> Adjusting the group of new users ..."
93         for item in ${_gids}; do
94                 _name=${item%:*}
95                 _gid=${item#*:}
96                 echo "   * ${_name}: ${_gid}"
97                 pw -V ${etcdir} usermod ${_name} -g ${_gid}
98         done
99 }
100
101 usage() {
102         cat > /dev/stderr << _EOF_
103 Add new users and groups.
104
105 Usage: ${0##*/} -d <etc-dir> -g <group-file> -p <master.passwd-file>
106
107 _EOF_
108
109         exit 1
110 }
111
112 ETC_DIR=
113 GROUP_FILE=
114 PASSWD_FILE=
115
116 while getopts :d:g:hp: opt; do
117         case ${opt} in
118         d)
119                 ETC_DIR=${OPTARG}
120                 ;;
121         g)
122                 GROUP_FILE=${OPTARG}
123                 ;;
124         p)
125                 PASSWD_FILE=${OPTARG}
126                 ;;
127         h | \? | :)
128                 usage
129                 ;;
130         esac
131 done
132
133 shift $((OPTIND - 1))
134 [ $# -eq 0 ] || usage
135 [ -n "${ETC_DIR}" ] || usage
136 [ -n "${GROUP_FILE}" ] || usage
137 [ -n "${PASSWD_FILE}" ] || usage
138
139 add_users "${ETC_DIR}" "${PASSWD_FILE}" "${GROUP_FILE}"
140
141 echo "Update password databases ..."
142 pwd_mkdb -p -d "${ETC_DIR}" "${ETC_DIR}/master.passwd"