rlm@1: #!/bin/bash rlm@1: # Copyright (c) 2004 Matthias S. Benkmann
rlm@1: # You may do everything with this code except misrepresent its origin. rlm@1: # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! rlm@1: rlm@1: #Package user home directories will be located under this directory rlm@1: homebase=/usr/src rlm@1: rlm@1: #Contents of following directory are copied into home directory when creating rlm@1: #a new package user (existing files will not be overwritten) rlm@1: skel=/etc/pkgusr/skel-package rlm@1: rlm@1: if [ $# -lt 7 ]; then rlm@1: echo 1>&2 'USAGE: ' rlm@1: echo 1>&2 'add_package_user \' rlm@1: echo 1>&2 ' [-d ]' rlm@1: echo 1>&2 rlm@1: echo 1>&2 'If a user account called exists, a message will be printed and' rlm@1: echo 1>&2 'everything will be left as-is. If a user account called does not' rlm@1: echo 1>&2 'exist, one will be created.' rlm@1: echo 1>&2 'The account'"'"'s primary group will be and the /etc/passwd' rlm@1: echo 1>&2 'description field will be set to . If a group called ' rlm@1: echo 1>&2 'does not already exist, one will be created.' rlm@1: echo 1>&2 'The new account will get the "install" group as a supplementary group. If' rlm@1: echo 1>&2 'a group named "install" does not exist, one will be created.' rlm@1: echo 1>&2 rlm@1: echo 1>&2 ' needs to be a valid string for the /etc/passwd description' rlm@1: echo 1>&2 ' field. This means, among other things, that it must not contain ":".' rlm@1: echo 1>&2 ' Don'"'"'t forget to properly quote if it contains spaces or' rlm@1: echo 1>&2 ' other characters interpreted by the shell!' rlm@1: echo 1>&2 rlm@1: echo 1>&2 '(incl.) and (excl.) determine the numeric range from which' rlm@1: echo 1>&2 ' the new account'"'"'s UID will be picked in the following way:' rlm@1: echo 1>&2 rlm@1: echo 1>&2 ' 1. If the range contains no unused UID => Exit with error.' rlm@1: echo 1>&2 ' 2. If -1 is still unused, find the greatest UID from the range' rlm@1: echo 1>&2 ' that is used and pick the number after that.' rlm@1: echo 1>&2 ' 3. If -1 is in use, pick the first unused number from the range.' rlm@1: echo 1>&2 rlm@1: echo 1>&2 '(incl.) and (excl.) determine the numeric range from which' rlm@1: echo 1>&2 ' to pick the GID for group and/or group "install", if it needs to be' rlm@1: echo 1>&2 ' created. The process for picking the GID is the same as that for the UID.' rlm@1: echo 1>&2 '' rlm@1: echo 1>&2 ' specifies the new user'"'"'s home directory. If it is not provided,' rlm@1: echo 1>&2 ' it will default to '"$homebase/ ." rlm@1: echo 1>&2 ' If the home directory does not exist yet it will be created, otherwise' rlm@1: echo 1>&2 ' the existing directory will be recursively chown'"'"'ed to the new user.' rlm@1: echo 1>&2 ' The home directory will be populated with a copy of the contents of' rlm@1: echo 1>&2 " $skel, but pre-existing files in the home directory" rlm@1: echo 1>&2 ' will not be overwritten. Note that symlinks will be copied as symlinks!' rlm@1: echo 1>&2 '' rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: grpfile=/etc/group rlm@1: passwd=/etc/passwd rlm@1: rlm@1: rlm@1: rlm@1: description=$1 rlm@1: name=$2 rlm@1: minuid=$3 rlm@1: maxuid=$4 rlm@1: gname=$5 rlm@1: mingid=$6 rlm@1: maxgid=$7 rlm@1: home=$homebase/$name rlm@1: rlm@1: set -- "$@" _eNd_OF_lisT_ rlm@1: while [ "$1" != "_eNd_OF_lisT_" ]; do rlm@1: case "$1" in rlm@1: -d) shift 1 rlm@1: if [ "$1" = "_eNd_OF_lisT_" ]; then rlm@1: echo 1>&2 "-d directory name missing!" rlm@1: exit 1 rlm@1: fi rlm@1: home="$1" rlm@1: shift 1 rlm@1: ;; rlm@1: *) temp="$1" rlm@1: shift 1 rlm@1: set -- "$@" "$temp" rlm@1: ;; rlm@1: esac rlm@1: done rlm@1: shift 1 #throw away _eNd_OF_lisT_ rlm@1: rlm@1: if [ $UID -ne 0 ]; then echo Please run this script as root. ; exit 1; fi rlm@1: rlm@1: #test if user already exists rlm@1: grep "^$name:.*" $passwd rlm@1: if [ $? -eq 0 ]; then rlm@1: echo 'Package user does already exist! Do su '$name' to do maintenance work.' rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: #test if minuid, maxuid, mingid and maxgid are integers, otherwise error rlm@1: error=0 rlm@1: expr ${minuid} + 1 2>/dev/null 1>&2 || error=1 rlm@1: expr ${maxuid} + 1 2>/dev/null 1>&2 || error=1 rlm@1: expr ${mingid} + 1 2>/dev/null 1>&2 || error=1 rlm@1: expr ${maxgid} + 1 2>/dev/null 1>&2 || error=1 rlm@1: rlm@1: if [ $error -eq 1 ]; then rlm@1: echo Error: Illegal numeric value! rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: if [ $minuid -ge $maxuid ]; then rlm@1: echo 'Error: minuid must be less than maxuid !' rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: if [ $mingid -ge $maxgid ]; then rlm@1: echo 'Error: mingid must be less than maxgid !' rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: rlm@1: uidlist=`cut -d : -f 3 $passwd | sort -n` rlm@1: rlm@1: #find last used UID within range rlm@1: u=0 rlm@1: for i in $uidlist rlm@1: do rlm@1: if [ $i -ge $maxuid ]; then break; fi rlm@1: if [ $i -ge $minuid ]; then u=$i; fi rlm@1: done rlm@1: rlm@1: #if no UID from the range is used, pick the first, otherwise pick the one rlm@1: #immediately following the last UID in use. rlm@1: if [ $u -eq 0 ]; then u=$minuid; else u=`expr $u + 1`; fi rlm@1: rlm@1: #if the UID determined above is >= maxuid (i.e. illegal) rlm@1: #then we look for the first unused uid in the range. rlm@1: if [ $u -ge $maxuid ]; then rlm@1: u=$minuid rlm@1: for i in $uidlist rlm@1: do rlm@1: if [ $u -eq $i ]; then u=`expr $u + 1` ; fi rlm@1: if [ $i -ge $maxuid ]; then break; fi rlm@1: done rlm@1: rlm@1: if [ $u -ge $maxuid ]; then rlm@1: echo Error: UID range is full! rlm@1: exit 1 rlm@1: fi rlm@1: fi rlm@1: rlm@1: echo Will create user $name with uid: $u rlm@1: rlm@1: unset uidlist rlm@1: rlm@1: ############################################################################# rlm@1: # group rlm@1: ############################################################################# rlm@1: rlm@1: #execute the following for gname and "install" to get gids for those 2 groups rlm@1: rlm@1: g=0 rlm@1: creategroup=0 rlm@1: for group in install $gname rlm@1: do rlm@1: oldg=$g #save gid from previous run rlm@1: createinstall=$creategroup rlm@1: creategroup=0 rlm@1: rlm@1: #test if group already exists and extract gid if so rlm@1: g=`grep ^${group}:.\* $grpfile | cut -d : -f 3 -` rlm@1: rlm@1: #if group does not exist, then check range for a free gid rlm@1: if [ z$g = z ]; then rlm@1: creategroup=1 rlm@1: rlm@1: gidlist=`cut -d : -f 3 $grpfile | sort -n` rlm@1: rlm@1: #find last used GID within range rlm@1: g=0 rlm@1: for i in $gidlist rlm@1: do rlm@1: if [ $i -ge $maxgid ]; then break; fi rlm@1: if [ $i -ge $mingid ]; then g=$i; fi rlm@1: done rlm@1: rlm@1: #if no GID from the range is used, pick the first, otherwise pick the one rlm@1: #immediately following the last GID in use. rlm@1: if [ $g -eq 0 ]; then g=$mingid; else g=`expr $g + 1`; fi rlm@1: rlm@1: #don't reuse gid from previous run rlm@1: if [ $g -eq $oldg ]; then g=`expr $g + 1`; fi rlm@1: rlm@1: #if the GID determined above is >= maxgid (i.e. illegal) rlm@1: #then we look for the first unused gid in the range. rlm@1: if [ $g -ge $maxgid ]; then rlm@1: g=$mingid rlm@1: for i in $gidlist rlm@1: do rlm@1: if [ $g -eq $i ]; then g=`expr $g + 1` ; fi rlm@1: if [ $g -eq $oldg ]; then g=`expr $g + 1` ; fi rlm@1: if [ $i -ge $maxgid ]; then break; fi rlm@1: done rlm@1: rlm@1: if [ $g -ge $maxgid ]; then rlm@1: echo Error: GID range is full! rlm@1: exit 1 rlm@1: fi rlm@1: fi rlm@1: fi rlm@1: done rlm@1: rlm@1: unset gidlist rlm@1: rlm@1: if [ $createinstall -eq 1 ]; then rlm@1: echo Creating group install with gid $oldg rlm@1: groupadd -g $oldg install || exit 1 rlm@1: else rlm@1: echo Group install has gid $oldg rlm@1: fi rlm@1: if [ $creategroup -eq 1 ]; then rlm@1: echo Creating group $gname with gid $g rlm@1: groupadd -g $g $gname || exit 1 rlm@1: else rlm@1: echo Group $gname has gid $g rlm@1: fi rlm@1: rlm@1: rlm@1: rlm@1: useradd -c "${description}" -d ${home} -g ${gname} -G install \ rlm@1: -s /bin/bash -u ${u} ${name} || exit 1 rlm@1: rlm@1: mkdir -p $home || exit 1 rlm@1: rlm@1: yes n|cp -ai -R ${skel}/{[^.],.[^.],..?}* ${home} 2>/dev/null >/dev/null rlm@1: rlm@1: cd ${home} rlm@1: chown --recursive ${u}:${g} . rlm@1: rlm@1: rlm@1: exit 0