rmuser.sh revision 107543
1#!/bin/sh 2# 3# Copyright (c) 2002 Michael Telahun Makonnen. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. The name of the author may not be used to endorse or promote products 14# derived from this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27# Email: Mike Makonnen <mtm@identd.net> 28# 29# $FreeBSD: head/usr.sbin/adduser/rmuser.sh 107543 2002-12-03 05:41:09Z scottl $ 30# 31 32ATJOBDIR="/var/at/jobs" 33CRONJOBDIR="/var/cron/tabs" 34MAILSPOOL="/var/mail" 35SIGKILL="-KILL" 36TEMPDIRS="/tmp /var/tmp /var/tmp/vi.recover" 37THISCMD=`/usr/bin/basename $0` 38 39# err msg 40# Display $msg on stderr. 41# 42err() { 43 echo 1>&2 ${THISCMD}: $* 44} 45 46# rm_files login 47# Removes files or empty directories belonging to $login from various 48# temporary directories. 49# 50rm_files() { 51 # The argument is required 52 [ -n $1 ] && login=$1 || return 53 54 for _dir in ${TEMPDIRS} ; do 55 if [ ! -d $_dir ]; then 56 err "$_dir is not a valid directory." 57 continue 58 fi 59 echo -n "Removing files owned by ($login) in $_dir:" 60 filecount=0 61 _ownedfiles=`find 2>/dev/null $_dir -maxdepth 1 -user $login -print` 62 for _file in $_ownedfiles ; do 63 rm -fd $_file 64 filecount=`expr $filecount + 1` 65 done 66 echo " $filecount removed." 67 done 68} 69 70# rm_mail login 71# Removes unix mail and pop daemon files belonging to the user 72# specified in the $login argument. 73# 74rm_mail() { 75 # The argument is required 76 [ -n $1 ] && login=$1 || return 77 78 echo -n "Removing mail spool(s) for ($login):" 79 if [ -f ${MAILSPOOL}/$login ]; then 80 echo -n " ${MAILSPOOL}/$login" 81 rm ${MAILSPOOL}/$login 82 fi 83 if [ -f ${MAILSPOOL}/${login}.pop ]; then 84 echo -n " ${MAILSPOOL}/${login}.pop" 85 rm ${MAILSPOOL}/${login}.pop 86 fi 87 echo '.' 88} 89 90# kill_procs login 91# Send a SIGKILL to all processes owned by $login. 92# 93kill_procs() { 94 # The argument is required 95 [ -n $1 ] && login=$1 || return 96 97 echo -n "Terminating all processes owned by ($login):" 98 killcount=0 99 proclist=`ps 2>/dev/null -U $login | grep -v '^\ *PID' | awk '{print $1}'` 100 for _pid in $proclist ; do 101 kill 2>/dev/null ${SIGKILL} $_pid 102 killcount=`expr $killcount + 1` 103 done 104 echo " ${SIGKILL} signal sent to $killcount processes." 105} 106 107# rm_at_jobs login 108# Remove at (1) jobs belonging to $login. 109# 110rm_at_jobs() { 111 # The argument is required 112 [ -n $1 ] && login=$1 || return 113 114 atjoblist=`find 2>/dev/null ${ATJOBDIR} -maxdepth 1 -user $login -print` 115 jobcount=0 116 echo -n "Removing at(1) jobs owned by ($login):" 117 for _atjob in $atjoblist ; do 118 rm -f $_atjob 119 jobcount=`expr $jobcount + 1` 120 done 121 echo " $jobcount removed." 122} 123 124# rm_crontab login 125# Removes crontab file belonging to user $login. 126# 127rm_crontab() { 128 # The argument is required 129 [ -n $1 ] && login=$1 || return 130 131 echo -n "Removing crontab for ($login):" 132 if [ -f ${CRONJOBDIR}/$login ]; then 133 echo -n " ${CRONJOBDIR}/$login" 134 rm -f ${CRONJOBDIR}/$login 135 fi 136 echo '.' 137} 138 139# rm_user login 140# Remove user $login from the system. This subroutine makes use 141# of the pw(8) command to remove a user from the system. The pw(8) 142# command will remove the specified user from the user database 143# and group file and remove any crontabs. His home 144# directory will be removed if it is owned by him and contains no 145# files or subdirectories owned by other users. Mail spool files will 146# also be removed. 147# 148rm_user() { 149 # The argument is required 150 [ -n $1 ] && login=$1 || return 151 152 echo -n "Removing user ($login)" 153 [ -n "$pw_rswitch" ] && echo -n " (including home directory)" 154 echo -n " from the system:" 155 pw userdel -n $login $pw_rswitch 156 echo ' Done.' 157} 158 159# prompt_yesno msg 160# Prompts the user with a $msg. The answer is expected to be 161# yes, no, or some variation thereof. This subroutine returns 0 162# if the answer was yes, 1 if it was not. 163# 164prompt_yesno() { 165 # The argument is required 166 [ -n "$1" ] && msg=$1 || return 167 168 while : ; do 169 echo -n $msg 170 read _ans 171 case $_ans in 172 [Nn][Oo]|[Nn]) 173 return 1 174 ;; 175 [Yy][Ee][Ss]|[Yy][Ee]|[Yy]) 176 return 0 177 ;; 178 *) 179 ;; 180 esac 181 done 182} 183 184# show_usage 185# (no arguments) 186# Display usage message. 187# 188show_usage() { 189 echo "usage: ${THISCMD} [-y] [-f file] [user ...]" 190 echo " if the -y switch is used, either the -f switch or" 191 echo " one or more user names must be given" 192} 193 194#### END SUBROUTINE DEFENITION #### 195 196ffile= 197fflag= 198procowner= 199pw_rswitch= 200userlist= 201yflag= 202 203procowner=`/usr/bin/id -u` 204if [ "$procowner" != "0" ]; then 205 err 'you must be root (0) to use this utility.' 206 exit 1 207fi 208 209args=`getopt 2>/dev/null yf: $*` 210if [ "$?" != "0" ]; then 211 show_usage 212 exit 1 213fi 214set -- $args 215for _switch ; do 216 case $_switch in 217 -y) 218 yflag=1 219 shift 220 ;; 221 -f) 222 fflag=1 223 ffile="$2" 224 shift; shift 225 ;; 226 --) 227 shift 228 break 229 ;; 230 esac 231done 232 233# Get user names from a file if the -f switch was used. Otherwise, 234# get them from the commandline arguments. If we're getting it 235# from a file, the file must be owned by and writable only by root. 236# 237if [ $fflag ]; then 238 _insecure=`find $ffile ! -user 0 -or -perm +0022` 239 if [ -n "$_insecure" ]; then 240 err "file ($ffile) must be owned by and writeable only by root." 241 exit 1 242 fi 243 if [ -r "$ffile" ]; then 244 userlist=`cat $ffile | while read _user _junk ; do 245 case $_user in 246 \#*|'') 247 ;; 248 *) 249 echo -n "$userlist $_user" 250 ;; 251 esac 252 done` 253 fi 254else 255 while [ $1 ] ; do 256 userlist="$userlist $1" 257 shift 258 done 259fi 260 261# If the -y or -f switch has been used and the list of users to remove 262# is empty it is a fatal error. Otherwise, prompt the user for a list 263# of one or more user names. 264# 265if [ ! "$userlist" ]; then 266 if [ $fflag ]; then 267 err "($ffile) does not exist or does not contain any user names." 268 exit 1 269 elif [ $yflag ]; then 270 show_usage 271 exit 1 272 else 273 echo -n "Please enter one or more user name's: " 274 read userlist 275 fi 276fi 277 278_user= 279_uid= 280for _user in $userlist ; do 281 # Make sure the name exists in the passwd database and that it 282 # does not have a uid of 0 283 # 284 userrec=`pw 2>/dev/null usershow -n $_user` 285 if [ "$?" != "0" ]; then 286 err "user ($_user) does not exist in the password database." 287 continue 288 fi 289 _uid=`echo $userrec | awk -F: '{print $3}'` 290 if [ "$_uid" = "0" ]; then 291 err "user ($_user) has uid 0. You may not remove this user." 292 continue 293 fi 294 295 # If the -y switch was not used ask for confirmation to remove the 296 # user and home directory. 297 # 298 if [ -z "$yflag" ]; then 299 echo "Matching password entry:" 300 echo 301 echo $userrec 302 echo 303 if ! prompt_yesno "Is this the entry you wish to remove? " ; then 304 continue 305 fi 306 _homedir=`echo $userrec | awk -F: '{print $9}'` 307 if prompt_yesno "Remove user's home directory ($_homedir)?: "; then 308 pw_rswitch="-r" 309 fi 310 else 311 pw_rswitch="-r" 312 fi 313 314 # Disable any further attempts to log into this account 315 pw 2>/dev/null lock $_user 316 317 # Remove crontab, mail spool, etc. Then obliterate the user from 318 # the passwd and group database. 319 rm_crontab $_user 320 rm_at_jobs $_user 321 kill_procs $_user 322 rm_mail $_user 323 rm_files $_user 324 rm_user $_user 325done 326