rlm@1
|
1 #!/bin/bash
|
rlm@1
|
2 # Copyright (c) 2004 Matthias S. Benkmann <article AT winterdrache DOT de>
|
rlm@1
|
3 # You may do everything with this code except misrepresent its origin.
|
rlm@1
|
4 # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND!
|
rlm@1
|
5
|
rlm@1
|
6 #Package user home directories will be located under this directory
|
rlm@1
|
7 homebase=/usr/src
|
rlm@1
|
8
|
rlm@1
|
9 #Contents of following directory are copied into home directory when creating
|
rlm@1
|
10 #a new package user (existing files will not be overwritten)
|
rlm@1
|
11 skel=/etc/pkgusr/skel-package
|
rlm@1
|
12
|
rlm@1
|
13 if [ $# -lt 7 ]; then
|
rlm@1
|
14 echo 1>&2 'USAGE: '
|
rlm@1
|
15 echo 1>&2 'add_package_user <description> <name> <minuid> <maxuid> \'
|
rlm@1
|
16 echo 1>&2 ' <group> <mingid> <maxgid> [-d <home>]'
|
rlm@1
|
17 echo 1>&2
|
rlm@1
|
18 echo 1>&2 'If a user account called <name> exists, a message will be printed and'
|
rlm@1
|
19 echo 1>&2 'everything will be left as-is. If a user account called <name> does not'
|
rlm@1
|
20 echo 1>&2 'exist, one will be created.'
|
rlm@1
|
21 echo 1>&2 'The account'"'"'s primary group will be <group> and the /etc/passwd'
|
rlm@1
|
22 echo 1>&2 'description field will be set to <description>. If a group called <group>'
|
rlm@1
|
23 echo 1>&2 'does not already exist, one will be created.'
|
rlm@1
|
24 echo 1>&2 'The new account will get the "install" group as a supplementary group. If'
|
rlm@1
|
25 echo 1>&2 'a group named "install" does not exist, one will be created.'
|
rlm@1
|
26 echo 1>&2
|
rlm@1
|
27 echo 1>&2 '<description> needs to be a valid string for the /etc/passwd description'
|
rlm@1
|
28 echo 1>&2 ' field. This means, among other things, that it must not contain ":".'
|
rlm@1
|
29 echo 1>&2 ' Don'"'"'t forget to properly quote <description> if it contains spaces or'
|
rlm@1
|
30 echo 1>&2 ' other characters interpreted by the shell!'
|
rlm@1
|
31 echo 1>&2
|
rlm@1
|
32 echo 1>&2 '<minuid>(incl.) and <maxuid>(excl.) determine the numeric range from which'
|
rlm@1
|
33 echo 1>&2 ' the new account'"'"'s UID will be picked in the following way:'
|
rlm@1
|
34 echo 1>&2
|
rlm@1
|
35 echo 1>&2 ' 1. If the range contains no unused UID => Exit with error.'
|
rlm@1
|
36 echo 1>&2 ' 2. If <maxuid>-1 is still unused, find the greatest UID from the range'
|
rlm@1
|
37 echo 1>&2 ' that is used and pick the number after that.'
|
rlm@1
|
38 echo 1>&2 ' 3. If <maxuid>-1 is in use, pick the first unused number from the range.'
|
rlm@1
|
39 echo 1>&2
|
rlm@1
|
40 echo 1>&2 '<mingid>(incl.) and <maxgid>(excl.) determine the numeric range from which'
|
rlm@1
|
41 echo 1>&2 ' to pick the GID for group <group> and/or group "install", if it needs to be'
|
rlm@1
|
42 echo 1>&2 ' created. The process for picking the GID is the same as that for the UID.'
|
rlm@1
|
43 echo 1>&2 ''
|
rlm@1
|
44 echo 1>&2 '<home> specifies the new user'"'"'s home directory. If it is not provided,'
|
rlm@1
|
45 echo 1>&2 ' it will default to '"$homebase/<name> ."
|
rlm@1
|
46 echo 1>&2 ' If the home directory does not exist yet it will be created, otherwise'
|
rlm@1
|
47 echo 1>&2 ' the existing directory will be recursively chown'"'"'ed to the new user.'
|
rlm@1
|
48 echo 1>&2 ' The home directory will be populated with a copy of the contents of'
|
rlm@1
|
49 echo 1>&2 " $skel, but pre-existing files in the home directory"
|
rlm@1
|
50 echo 1>&2 ' will not be overwritten. Note that symlinks will be copied as symlinks!'
|
rlm@1
|
51 echo 1>&2 ''
|
rlm@1
|
52 exit 1
|
rlm@1
|
53 fi
|
rlm@1
|
54
|
rlm@1
|
55 grpfile=/etc/group
|
rlm@1
|
56 passwd=/etc/passwd
|
rlm@1
|
57
|
rlm@1
|
58
|
rlm@1
|
59
|
rlm@1
|
60 description=$1
|
rlm@1
|
61 name=$2
|
rlm@1
|
62 minuid=$3
|
rlm@1
|
63 maxuid=$4
|
rlm@1
|
64 gname=$5
|
rlm@1
|
65 mingid=$6
|
rlm@1
|
66 maxgid=$7
|
rlm@1
|
67 home=$homebase/$name
|
rlm@1
|
68
|
rlm@1
|
69 set -- "$@" _eNd_OF_lisT_
|
rlm@1
|
70 while [ "$1" != "_eNd_OF_lisT_" ]; do
|
rlm@1
|
71 case "$1" in
|
rlm@1
|
72 -d) shift 1
|
rlm@1
|
73 if [ "$1" = "_eNd_OF_lisT_" ]; then
|
rlm@1
|
74 echo 1>&2 "-d directory name missing!"
|
rlm@1
|
75 exit 1
|
rlm@1
|
76 fi
|
rlm@1
|
77 home="$1"
|
rlm@1
|
78 shift 1
|
rlm@1
|
79 ;;
|
rlm@1
|
80 *) temp="$1"
|
rlm@1
|
81 shift 1
|
rlm@1
|
82 set -- "$@" "$temp"
|
rlm@1
|
83 ;;
|
rlm@1
|
84 esac
|
rlm@1
|
85 done
|
rlm@1
|
86 shift 1 #throw away _eNd_OF_lisT_
|
rlm@1
|
87
|
rlm@1
|
88 if [ $UID -ne 0 ]; then echo Please run this script as root. ; exit 1; fi
|
rlm@1
|
89
|
rlm@1
|
90 #test if user already exists
|
rlm@1
|
91 grep "^$name:.*" $passwd
|
rlm@1
|
92 if [ $? -eq 0 ]; then
|
rlm@1
|
93 echo 'Package user does already exist! Do su '$name' to do maintenance work.'
|
rlm@1
|
94 exit 1
|
rlm@1
|
95 fi
|
rlm@1
|
96
|
rlm@1
|
97 #test if minuid, maxuid, mingid and maxgid are integers, otherwise error
|
rlm@1
|
98 error=0
|
rlm@1
|
99 expr ${minuid} + 1 2>/dev/null 1>&2 || error=1
|
rlm@1
|
100 expr ${maxuid} + 1 2>/dev/null 1>&2 || error=1
|
rlm@1
|
101 expr ${mingid} + 1 2>/dev/null 1>&2 || error=1
|
rlm@1
|
102 expr ${maxgid} + 1 2>/dev/null 1>&2 || error=1
|
rlm@1
|
103
|
rlm@1
|
104 if [ $error -eq 1 ]; then
|
rlm@1
|
105 echo Error: Illegal numeric value!
|
rlm@1
|
106 exit 1
|
rlm@1
|
107 fi
|
rlm@1
|
108
|
rlm@1
|
109 if [ $minuid -ge $maxuid ]; then
|
rlm@1
|
110 echo 'Error: minuid must be less than maxuid !'
|
rlm@1
|
111 exit 1
|
rlm@1
|
112 fi
|
rlm@1
|
113
|
rlm@1
|
114 if [ $mingid -ge $maxgid ]; then
|
rlm@1
|
115 echo 'Error: mingid must be less than maxgid !'
|
rlm@1
|
116 exit 1
|
rlm@1
|
117 fi
|
rlm@1
|
118
|
rlm@1
|
119
|
rlm@1
|
120 uidlist=`cut -d : -f 3 $passwd | sort -n`
|
rlm@1
|
121
|
rlm@1
|
122 #find last used UID within range
|
rlm@1
|
123 u=0
|
rlm@1
|
124 for i in $uidlist
|
rlm@1
|
125 do
|
rlm@1
|
126 if [ $i -ge $maxuid ]; then break; fi
|
rlm@1
|
127 if [ $i -ge $minuid ]; then u=$i; fi
|
rlm@1
|
128 done
|
rlm@1
|
129
|
rlm@1
|
130 #if no UID from the range is used, pick the first, otherwise pick the one
|
rlm@1
|
131 #immediately following the last UID in use.
|
rlm@1
|
132 if [ $u -eq 0 ]; then u=$minuid; else u=`expr $u + 1`; fi
|
rlm@1
|
133
|
rlm@1
|
134 #if the UID determined above is >= maxuid (i.e. illegal)
|
rlm@1
|
135 #then we look for the first unused uid in the range.
|
rlm@1
|
136 if [ $u -ge $maxuid ]; then
|
rlm@1
|
137 u=$minuid
|
rlm@1
|
138 for i in $uidlist
|
rlm@1
|
139 do
|
rlm@1
|
140 if [ $u -eq $i ]; then u=`expr $u + 1` ; fi
|
rlm@1
|
141 if [ $i -ge $maxuid ]; then break; fi
|
rlm@1
|
142 done
|
rlm@1
|
143
|
rlm@1
|
144 if [ $u -ge $maxuid ]; then
|
rlm@1
|
145 echo Error: UID range is full!
|
rlm@1
|
146 exit 1
|
rlm@1
|
147 fi
|
rlm@1
|
148 fi
|
rlm@1
|
149
|
rlm@1
|
150 echo Will create user $name with uid: $u
|
rlm@1
|
151
|
rlm@1
|
152 unset uidlist
|
rlm@1
|
153
|
rlm@1
|
154 #############################################################################
|
rlm@1
|
155 # group
|
rlm@1
|
156 #############################################################################
|
rlm@1
|
157
|
rlm@1
|
158 #execute the following for gname and "install" to get gids for those 2 groups
|
rlm@1
|
159
|
rlm@1
|
160 g=0
|
rlm@1
|
161 creategroup=0
|
rlm@1
|
162 for group in install $gname
|
rlm@1
|
163 do
|
rlm@1
|
164 oldg=$g #save gid from previous run
|
rlm@1
|
165 createinstall=$creategroup
|
rlm@1
|
166 creategroup=0
|
rlm@1
|
167
|
rlm@1
|
168 #test if group already exists and extract gid if so
|
rlm@1
|
169 g=`grep ^${group}:.\* $grpfile | cut -d : -f 3 -`
|
rlm@1
|
170
|
rlm@1
|
171 #if group does not exist, then check range for a free gid
|
rlm@1
|
172 if [ z$g = z ]; then
|
rlm@1
|
173 creategroup=1
|
rlm@1
|
174
|
rlm@1
|
175 gidlist=`cut -d : -f 3 $grpfile | sort -n`
|
rlm@1
|
176
|
rlm@1
|
177 #find last used GID within range
|
rlm@1
|
178 g=0
|
rlm@1
|
179 for i in $gidlist
|
rlm@1
|
180 do
|
rlm@1
|
181 if [ $i -ge $maxgid ]; then break; fi
|
rlm@1
|
182 if [ $i -ge $mingid ]; then g=$i; fi
|
rlm@1
|
183 done
|
rlm@1
|
184
|
rlm@1
|
185 #if no GID from the range is used, pick the first, otherwise pick the one
|
rlm@1
|
186 #immediately following the last GID in use.
|
rlm@1
|
187 if [ $g -eq 0 ]; then g=$mingid; else g=`expr $g + 1`; fi
|
rlm@1
|
188
|
rlm@1
|
189 #don't reuse gid from previous run
|
rlm@1
|
190 if [ $g -eq $oldg ]; then g=`expr $g + 1`; fi
|
rlm@1
|
191
|
rlm@1
|
192 #if the GID determined above is >= maxgid (i.e. illegal)
|
rlm@1
|
193 #then we look for the first unused gid in the range.
|
rlm@1
|
194 if [ $g -ge $maxgid ]; then
|
rlm@1
|
195 g=$mingid
|
rlm@1
|
196 for i in $gidlist
|
rlm@1
|
197 do
|
rlm@1
|
198 if [ $g -eq $i ]; then g=`expr $g + 1` ; fi
|
rlm@1
|
199 if [ $g -eq $oldg ]; then g=`expr $g + 1` ; fi
|
rlm@1
|
200 if [ $i -ge $maxgid ]; then break; fi
|
rlm@1
|
201 done
|
rlm@1
|
202
|
rlm@1
|
203 if [ $g -ge $maxgid ]; then
|
rlm@1
|
204 echo Error: GID range is full!
|
rlm@1
|
205 exit 1
|
rlm@1
|
206 fi
|
rlm@1
|
207 fi
|
rlm@1
|
208 fi
|
rlm@1
|
209 done
|
rlm@1
|
210
|
rlm@1
|
211 unset gidlist
|
rlm@1
|
212
|
rlm@1
|
213 if [ $createinstall -eq 1 ]; then
|
rlm@1
|
214 echo Creating group install with gid $oldg
|
rlm@1
|
215 groupadd -g $oldg install || exit 1
|
rlm@1
|
216 else
|
rlm@1
|
217 echo Group install has gid $oldg
|
rlm@1
|
218 fi
|
rlm@1
|
219 if [ $creategroup -eq 1 ]; then
|
rlm@1
|
220 echo Creating group $gname with gid $g
|
rlm@1
|
221 groupadd -g $g $gname || exit 1
|
rlm@1
|
222 else
|
rlm@1
|
223 echo Group $gname has gid $g
|
rlm@1
|
224 fi
|
rlm@1
|
225
|
rlm@1
|
226
|
rlm@1
|
227
|
rlm@1
|
228 useradd -c "${description}" -d ${home} -g ${gname} -G install \
|
rlm@1
|
229 -s /bin/bash -u ${u} ${name} || exit 1
|
rlm@1
|
230
|
rlm@1
|
231 mkdir -p $home || exit 1
|
rlm@1
|
232
|
rlm@1
|
233 yes n|cp -ai -R ${skel}/{[^.],.[^.],..?}* ${home} 2>/dev/null >/dev/null
|
rlm@1
|
234
|
rlm@1
|
235 cd ${home}
|
rlm@1
|
236 chown --recursive ${u}:${g} .
|
rlm@1
|
237
|
rlm@1
|
238
|
rlm@1
|
239 exit 0
|