rmuser.sh revision 109752
1107543Sscottl#!/bin/sh 2107543Sscottl# 3107543Sscottl# Copyright (c) 2002 Michael Telahun Makonnen. All rights reserved. 4107543Sscottl# 5107543Sscottl# Redistribution and use in source and binary forms, with or without 6107543Sscottl# modification, are permitted provided that the following conditions 7107543Sscottl# are met: 8107543Sscottl# 1. Redistributions of source code must retain the above copyright 9107543Sscottl# notice, this list of conditions and the following disclaimer. 10107543Sscottl# 2. Redistributions in binary form must reproduce the above copyright 11107543Sscottl# notice, this list of conditions and the following disclaimer in the 12107543Sscottl# documentation and/or other materials provided with the distribution. 13107543Sscottl# 3. The name of the author may not be used to endorse or promote products 14107543Sscottl# derived from this software without specific prior written permission. 15107543Sscottl# 16107543Sscottl# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17107543Sscottl# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18107543Sscottl# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19107543Sscottl# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20107543Sscottl# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21107543Sscottl# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22107543Sscottl# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23107543Sscottl# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24107543Sscottl# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25107543Sscottl# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26107543Sscottl# 27107543Sscottl# Email: Mike Makonnen <mtm@identd.net> 28107543Sscottl# 29107543Sscottl# $FreeBSD: head/usr.sbin/adduser/rmuser.sh 109752 2003-01-23 20:18:21Z fjoe $ 30107543Sscottl# 31107543Sscottl 32107543SscottlATJOBDIR="/var/at/jobs" 33107543SscottlCRONJOBDIR="/var/cron/tabs" 34107543SscottlMAILSPOOL="/var/mail" 35107543SscottlSIGKILL="-KILL" 36107694StjrTEMPDIRS="/tmp /var/tmp" 37107543SscottlTHISCMD=`/usr/bin/basename $0` 38107543Sscottl 39107543Sscottl# err msg 40107543Sscottl# Display $msg on stderr. 41107543Sscottl# 42107543Sscottlerr() { 43107543Sscottl echo 1>&2 ${THISCMD}: $* 44107543Sscottl} 45107543Sscottl 46107543Sscottl# rm_files login 47107543Sscottl# Removes files or empty directories belonging to $login from various 48107543Sscottl# temporary directories. 49107543Sscottl# 50107543Sscottlrm_files() { 51107543Sscottl # The argument is required 52107543Sscottl [ -n $1 ] && login=$1 || return 53107543Sscottl 54107543Sscottl for _dir in ${TEMPDIRS} ; do 55107543Sscottl if [ ! -d $_dir ]; then 56107543Sscottl err "$_dir is not a valid directory." 57107543Sscottl continue 58107543Sscottl fi 59107543Sscottl echo -n "Removing files owned by ($login) in $_dir:" 60107694Stjr filecount=`find 2>/dev/null "$_dir" -user "$login" -delete -print | \ 61107694Stjr wc -l | sed 's/ *//'` 62107543Sscottl echo " $filecount removed." 63107543Sscottl done 64107543Sscottl} 65107543Sscottl 66107543Sscottl# rm_mail login 67107543Sscottl# Removes unix mail and pop daemon files belonging to the user 68107543Sscottl# specified in the $login argument. 69107543Sscottl# 70107543Sscottlrm_mail() { 71107543Sscottl # The argument is required 72107543Sscottl [ -n $1 ] && login=$1 || return 73107543Sscottl 74107543Sscottl echo -n "Removing mail spool(s) for ($login):" 75107543Sscottl if [ -f ${MAILSPOOL}/$login ]; then 76107543Sscottl echo -n " ${MAILSPOOL}/$login" 77107543Sscottl rm ${MAILSPOOL}/$login 78107543Sscottl fi 79107543Sscottl if [ -f ${MAILSPOOL}/${login}.pop ]; then 80107543Sscottl echo -n " ${MAILSPOOL}/${login}.pop" 81107543Sscottl rm ${MAILSPOOL}/${login}.pop 82107543Sscottl fi 83107543Sscottl echo '.' 84107543Sscottl} 85107543Sscottl 86107543Sscottl# kill_procs login 87107543Sscottl# Send a SIGKILL to all processes owned by $login. 88107543Sscottl# 89107543Sscottlkill_procs() { 90107543Sscottl # The argument is required 91107543Sscottl [ -n $1 ] && login=$1 || return 92107543Sscottl 93107543Sscottl echo -n "Terminating all processes owned by ($login):" 94107543Sscottl killcount=0 95107543Sscottl proclist=`ps 2>/dev/null -U $login | grep -v '^\ *PID' | awk '{print $1}'` 96107543Sscottl for _pid in $proclist ; do 97107543Sscottl kill 2>/dev/null ${SIGKILL} $_pid 98109752Sfjoe killcount=$(($killcount + 1)) 99107543Sscottl done 100107543Sscottl echo " ${SIGKILL} signal sent to $killcount processes." 101107543Sscottl} 102107543Sscottl 103107543Sscottl# rm_at_jobs login 104107543Sscottl# Remove at (1) jobs belonging to $login. 105107543Sscottl# 106107543Sscottlrm_at_jobs() { 107107543Sscottl # The argument is required 108107543Sscottl [ -n $1 ] && login=$1 || return 109107543Sscottl 110107543Sscottl atjoblist=`find 2>/dev/null ${ATJOBDIR} -maxdepth 1 -user $login -print` 111107543Sscottl jobcount=0 112107543Sscottl echo -n "Removing at(1) jobs owned by ($login):" 113107543Sscottl for _atjob in $atjoblist ; do 114107543Sscottl rm -f $_atjob 115109752Sfjoe jobcount=$(($jobcount + 1)) 116107543Sscottl done 117107543Sscottl echo " $jobcount removed." 118107543Sscottl} 119107543Sscottl 120107543Sscottl# rm_crontab login 121107543Sscottl# Removes crontab file belonging to user $login. 122107543Sscottl# 123107543Sscottlrm_crontab() { 124107543Sscottl # The argument is required 125107543Sscottl [ -n $1 ] && login=$1 || return 126107543Sscottl 127107543Sscottl echo -n "Removing crontab for ($login):" 128107543Sscottl if [ -f ${CRONJOBDIR}/$login ]; then 129107543Sscottl echo -n " ${CRONJOBDIR}/$login" 130107543Sscottl rm -f ${CRONJOBDIR}/$login 131107543Sscottl fi 132107543Sscottl echo '.' 133107543Sscottl} 134107543Sscottl 135107543Sscottl# rm_user login 136107543Sscottl# Remove user $login from the system. This subroutine makes use 137107543Sscottl# of the pw(8) command to remove a user from the system. The pw(8) 138107543Sscottl# command will remove the specified user from the user database 139107543Sscottl# and group file and remove any crontabs. His home 140107543Sscottl# directory will be removed if it is owned by him and contains no 141107543Sscottl# files or subdirectories owned by other users. Mail spool files will 142107543Sscottl# also be removed. 143107543Sscottl# 144107543Sscottlrm_user() { 145107543Sscottl # The argument is required 146107543Sscottl [ -n $1 ] && login=$1 || return 147107543Sscottl 148107543Sscottl echo -n "Removing user ($login)" 149107543Sscottl [ -n "$pw_rswitch" ] && echo -n " (including home directory)" 150107543Sscottl echo -n " from the system:" 151107543Sscottl pw userdel -n $login $pw_rswitch 152107543Sscottl echo ' Done.' 153107543Sscottl} 154107543Sscottl 155107543Sscottl# prompt_yesno msg 156107543Sscottl# Prompts the user with a $msg. The answer is expected to be 157107543Sscottl# yes, no, or some variation thereof. This subroutine returns 0 158107543Sscottl# if the answer was yes, 1 if it was not. 159107543Sscottl# 160107543Sscottlprompt_yesno() { 161107543Sscottl # The argument is required 162109750Sfjoe [ -n "$1" ] && msg="$1" || return 163107543Sscottl 164107543Sscottl while : ; do 165109750Sfjoe echo -n "$msg" 166107543Sscottl read _ans 167107543Sscottl case $_ans in 168107543Sscottl [Nn][Oo]|[Nn]) 169107543Sscottl return 1 170107543Sscottl ;; 171107543Sscottl [Yy][Ee][Ss]|[Yy][Ee]|[Yy]) 172107543Sscottl return 0 173107543Sscottl ;; 174107543Sscottl *) 175107543Sscottl ;; 176107543Sscottl esac 177107543Sscottl done 178107543Sscottl} 179107543Sscottl 180107543Sscottl# show_usage 181107543Sscottl# (no arguments) 182107543Sscottl# Display usage message. 183107543Sscottl# 184107543Sscottlshow_usage() { 185107543Sscottl echo "usage: ${THISCMD} [-y] [-f file] [user ...]" 186107543Sscottl echo " if the -y switch is used, either the -f switch or" 187107543Sscottl echo " one or more user names must be given" 188107543Sscottl} 189107543Sscottl 190107543Sscottl#### END SUBROUTINE DEFENITION #### 191107543Sscottl 192107543Sscottlffile= 193107543Sscottlfflag= 194107543Sscottlprocowner= 195107543Sscottlpw_rswitch= 196107543Sscottluserlist= 197107543Sscottlyflag= 198107543Sscottl 199107543Sscottlprocowner=`/usr/bin/id -u` 200107543Sscottlif [ "$procowner" != "0" ]; then 201107543Sscottl err 'you must be root (0) to use this utility.' 202107543Sscottl exit 1 203107543Sscottlfi 204107543Sscottl 205107543Sscottlargs=`getopt 2>/dev/null yf: $*` 206107543Sscottlif [ "$?" != "0" ]; then 207107543Sscottl show_usage 208107543Sscottl exit 1 209107543Sscottlfi 210107543Sscottlset -- $args 211107543Sscottlfor _switch ; do 212107543Sscottl case $_switch in 213107543Sscottl -y) 214107543Sscottl yflag=1 215107543Sscottl shift 216107543Sscottl ;; 217107543Sscottl -f) 218107543Sscottl fflag=1 219107543Sscottl ffile="$2" 220107543Sscottl shift; shift 221107543Sscottl ;; 222107543Sscottl --) 223107543Sscottl shift 224107543Sscottl break 225107543Sscottl ;; 226107543Sscottl esac 227107543Sscottldone 228107543Sscottl 229107543Sscottl# Get user names from a file if the -f switch was used. Otherwise, 230107543Sscottl# get them from the commandline arguments. If we're getting it 231107543Sscottl# from a file, the file must be owned by and writable only by root. 232107543Sscottl# 233107543Sscottlif [ $fflag ]; then 234107543Sscottl _insecure=`find $ffile ! -user 0 -or -perm +0022` 235107543Sscottl if [ -n "$_insecure" ]; then 236107543Sscottl err "file ($ffile) must be owned by and writeable only by root." 237107543Sscottl exit 1 238107543Sscottl fi 239107543Sscottl if [ -r "$ffile" ]; then 240107543Sscottl userlist=`cat $ffile | while read _user _junk ; do 241107543Sscottl case $_user in 242107543Sscottl \#*|'') 243107543Sscottl ;; 244107543Sscottl *) 245107543Sscottl echo -n "$userlist $_user" 246107543Sscottl ;; 247107543Sscottl esac 248107543Sscottl done` 249107543Sscottl fi 250107543Sscottlelse 251107543Sscottl while [ $1 ] ; do 252107543Sscottl userlist="$userlist $1" 253107543Sscottl shift 254107543Sscottl done 255107543Sscottlfi 256107543Sscottl 257107543Sscottl# If the -y or -f switch has been used and the list of users to remove 258107543Sscottl# is empty it is a fatal error. Otherwise, prompt the user for a list 259107543Sscottl# of one or more user names. 260107543Sscottl# 261107543Sscottlif [ ! "$userlist" ]; then 262107543Sscottl if [ $fflag ]; then 263107543Sscottl err "($ffile) does not exist or does not contain any user names." 264107543Sscottl exit 1 265107543Sscottl elif [ $yflag ]; then 266107543Sscottl show_usage 267107543Sscottl exit 1 268107543Sscottl else 269107543Sscottl echo -n "Please enter one or more user name's: " 270107543Sscottl read userlist 271107543Sscottl fi 272107543Sscottlfi 273107543Sscottl 274107543Sscottl_user= 275107543Sscottl_uid= 276107543Sscottlfor _user in $userlist ; do 277107543Sscottl # Make sure the name exists in the passwd database and that it 278107543Sscottl # does not have a uid of 0 279107543Sscottl # 280107543Sscottl userrec=`pw 2>/dev/null usershow -n $_user` 281107543Sscottl if [ "$?" != "0" ]; then 282107543Sscottl err "user ($_user) does not exist in the password database." 283107543Sscottl continue 284107543Sscottl fi 285107543Sscottl _uid=`echo $userrec | awk -F: '{print $3}'` 286107543Sscottl if [ "$_uid" = "0" ]; then 287107543Sscottl err "user ($_user) has uid 0. You may not remove this user." 288107543Sscottl continue 289107543Sscottl fi 290107543Sscottl 291107543Sscottl # If the -y switch was not used ask for confirmation to remove the 292107543Sscottl # user and home directory. 293107543Sscottl # 294107543Sscottl if [ -z "$yflag" ]; then 295107543Sscottl echo "Matching password entry:" 296107543Sscottl echo 297107543Sscottl echo $userrec 298107543Sscottl echo 299107543Sscottl if ! prompt_yesno "Is this the entry you wish to remove? " ; then 300107543Sscottl continue 301107543Sscottl fi 302107543Sscottl _homedir=`echo $userrec | awk -F: '{print $9}'` 303109750Sfjoe if prompt_yesno "Remove user's home directory ($_homedir)? "; then 304107543Sscottl pw_rswitch="-r" 305107543Sscottl fi 306107543Sscottl else 307107543Sscottl pw_rswitch="-r" 308107543Sscottl fi 309107543Sscottl 310107543Sscottl # Disable any further attempts to log into this account 311107543Sscottl pw 2>/dev/null lock $_user 312107543Sscottl 313107543Sscottl # Remove crontab, mail spool, etc. Then obliterate the user from 314107543Sscottl # the passwd and group database. 315107543Sscottl rm_crontab $_user 316107543Sscottl rm_at_jobs $_user 317107543Sscottl kill_procs $_user 318107543Sscottl rm_mail $_user 319107543Sscottl rm_files $_user 320107543Sscottl rm_user $_user 321107543Sscottldone 322