17cdfce09SScott Long#!/bin/sh 27cdfce09SScott Long# 37cdfce09SScott Long# Copyright (c) 2002 Michael Telahun Makonnen. All rights reserved. 47cdfce09SScott Long# 57cdfce09SScott Long# Redistribution and use in source and binary forms, with or without 67cdfce09SScott Long# modification, are permitted provided that the following conditions 77cdfce09SScott Long# are met: 87cdfce09SScott Long# 1. Redistributions of source code must retain the above copyright 97cdfce09SScott Long# notice, this list of conditions and the following disclaimer. 107cdfce09SScott Long# 2. Redistributions in binary form must reproduce the above copyright 117cdfce09SScott Long# notice, this list of conditions and the following disclaimer in the 127cdfce09SScott Long# documentation and/or other materials provided with the distribution. 137cdfce09SScott Long# 3. The name of the author may not be used to endorse or promote products 147cdfce09SScott Long# derived from this software without specific prior written permission. 157cdfce09SScott Long# 167cdfce09SScott Long# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 177cdfce09SScott Long# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 187cdfce09SScott Long# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 197cdfce09SScott Long# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 207cdfce09SScott Long# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 217cdfce09SScott Long# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 227cdfce09SScott Long# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 237cdfce09SScott Long# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 247cdfce09SScott Long# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 257cdfce09SScott Long# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 267cdfce09SScott Long# 277cdfce09SScott Long# Email: Mike Makonnen <mtm@identd.net> 287cdfce09SScott Long# 297cdfce09SScott Long# $FreeBSD$ 307cdfce09SScott Long# 317cdfce09SScott Long 327cdfce09SScott LongATJOBDIR="/var/at/jobs" 337cdfce09SScott LongCRONJOBDIR="/var/cron/tabs" 347cdfce09SScott LongMAILSPOOL="/var/mail" 357cdfce09SScott LongSIGKILL="-KILL" 36deca89c7STim J. RobbinsTEMPDIRS="/tmp /var/tmp" 377cdfce09SScott LongTHISCMD=`/usr/bin/basename $0` 387cdfce09SScott Long 397cdfce09SScott Long# err msg 407cdfce09SScott Long# Display $msg on stderr. 417cdfce09SScott Long# 427cdfce09SScott Longerr() { 437cdfce09SScott Long echo 1>&2 ${THISCMD}: $* 447cdfce09SScott Long} 457cdfce09SScott Long 467cdfce09SScott Long# rm_files login 477cdfce09SScott Long# Removes files or empty directories belonging to $login from various 487cdfce09SScott Long# temporary directories. 497cdfce09SScott Long# 507cdfce09SScott Longrm_files() { 517cdfce09SScott Long # The argument is required 527cdfce09SScott Long [ -n $1 ] && login=$1 || return 537cdfce09SScott Long 547cdfce09SScott Long for _dir in ${TEMPDIRS} ; do 557cdfce09SScott Long if [ ! -d $_dir ]; then 567cdfce09SScott Long err "$_dir is not a valid directory." 577cdfce09SScott Long continue 587cdfce09SScott Long fi 597cdfce09SScott Long echo -n "Removing files owned by ($login) in $_dir:" 60deca89c7STim J. Robbins filecount=`find 2>/dev/null "$_dir" -user "$login" -delete -print | \ 61deca89c7STim J. Robbins wc -l | sed 's/ *//'` 627cdfce09SScott Long echo " $filecount removed." 637cdfce09SScott Long done 647cdfce09SScott Long} 657cdfce09SScott Long 667cdfce09SScott Long# rm_mail login 677cdfce09SScott Long# Removes unix mail and pop daemon files belonging to the user 687cdfce09SScott Long# specified in the $login argument. 697cdfce09SScott Long# 707cdfce09SScott Longrm_mail() { 717cdfce09SScott Long # The argument is required 727cdfce09SScott Long [ -n $1 ] && login=$1 || return 737cdfce09SScott Long 747cdfce09SScott Long echo -n "Removing mail spool(s) for ($login):" 757cdfce09SScott Long if [ -f ${MAILSPOOL}/$login ]; then 767cdfce09SScott Long echo -n " ${MAILSPOOL}/$login" 777cdfce09SScott Long rm ${MAILSPOOL}/$login 787cdfce09SScott Long fi 797cdfce09SScott Long if [ -f ${MAILSPOOL}/${login}.pop ]; then 807cdfce09SScott Long echo -n " ${MAILSPOOL}/${login}.pop" 817cdfce09SScott Long rm ${MAILSPOOL}/${login}.pop 827cdfce09SScott Long fi 837cdfce09SScott Long echo '.' 847cdfce09SScott Long} 857cdfce09SScott Long 867cdfce09SScott Long# kill_procs login 877cdfce09SScott Long# Send a SIGKILL to all processes owned by $login. 887cdfce09SScott Long# 897cdfce09SScott Longkill_procs() { 907cdfce09SScott Long # The argument is required 917cdfce09SScott Long [ -n $1 ] && login=$1 || return 927cdfce09SScott Long 937cdfce09SScott Long echo -n "Terminating all processes owned by ($login):" 947cdfce09SScott Long killcount=0 957cdfce09SScott Long proclist=`ps 2>/dev/null -U $login | grep -v '^\ *PID' | awk '{print $1}'` 967cdfce09SScott Long for _pid in $proclist ; do 977cdfce09SScott Long kill 2>/dev/null ${SIGKILL} $_pid 98fd045cf5SMax Khon killcount=$(($killcount + 1)) 997cdfce09SScott Long done 1007cdfce09SScott Long echo " ${SIGKILL} signal sent to $killcount processes." 1017cdfce09SScott Long} 1027cdfce09SScott Long 1037cdfce09SScott Long# rm_at_jobs login 1047cdfce09SScott Long# Remove at (1) jobs belonging to $login. 1057cdfce09SScott Long# 1067cdfce09SScott Longrm_at_jobs() { 1077cdfce09SScott Long # The argument is required 1087cdfce09SScott Long [ -n $1 ] && login=$1 || return 1097cdfce09SScott Long 1107cdfce09SScott Long atjoblist=`find 2>/dev/null ${ATJOBDIR} -maxdepth 1 -user $login -print` 1117cdfce09SScott Long jobcount=0 1127cdfce09SScott Long echo -n "Removing at(1) jobs owned by ($login):" 1137cdfce09SScott Long for _atjob in $atjoblist ; do 1147cdfce09SScott Long rm -f $_atjob 115fd045cf5SMax Khon jobcount=$(($jobcount + 1)) 1167cdfce09SScott Long done 1177cdfce09SScott Long echo " $jobcount removed." 1187cdfce09SScott Long} 1197cdfce09SScott Long 1207cdfce09SScott Long# rm_crontab login 1217cdfce09SScott Long# Removes crontab file belonging to user $login. 1227cdfce09SScott Long# 1237cdfce09SScott Longrm_crontab() { 1247cdfce09SScott Long # The argument is required 1257cdfce09SScott Long [ -n $1 ] && login=$1 || return 1267cdfce09SScott Long 1277cdfce09SScott Long echo -n "Removing crontab for ($login):" 1287cdfce09SScott Long if [ -f ${CRONJOBDIR}/$login ]; then 1297cdfce09SScott Long echo -n " ${CRONJOBDIR}/$login" 1307cdfce09SScott Long rm -f ${CRONJOBDIR}/$login 1317cdfce09SScott Long fi 1327cdfce09SScott Long echo '.' 1337cdfce09SScott Long} 1347cdfce09SScott Long 1357cdfce09SScott Long# rm_user login 1367cdfce09SScott Long# Remove user $login from the system. This subroutine makes use 1377cdfce09SScott Long# of the pw(8) command to remove a user from the system. The pw(8) 1387cdfce09SScott Long# command will remove the specified user from the user database 1397cdfce09SScott Long# and group file and remove any crontabs. His home 1407cdfce09SScott Long# directory will be removed if it is owned by him and contains no 1417cdfce09SScott Long# files or subdirectories owned by other users. Mail spool files will 1427cdfce09SScott Long# also be removed. 1437cdfce09SScott Long# 1447cdfce09SScott Longrm_user() { 1457cdfce09SScott Long # The argument is required 1467cdfce09SScott Long [ -n $1 ] && login=$1 || return 1477cdfce09SScott Long 1487cdfce09SScott Long echo -n "Removing user ($login)" 1497cdfce09SScott Long [ -n "$pw_rswitch" ] && echo -n " (including home directory)" 1507cdfce09SScott Long echo -n " from the system:" 1517cdfce09SScott Long pw userdel -n $login $pw_rswitch 1527cdfce09SScott Long echo ' Done.' 1537cdfce09SScott Long} 1547cdfce09SScott Long 1557cdfce09SScott Long# prompt_yesno msg 1567cdfce09SScott Long# Prompts the user with a $msg. The answer is expected to be 1577cdfce09SScott Long# yes, no, or some variation thereof. This subroutine returns 0 1587cdfce09SScott Long# if the answer was yes, 1 if it was not. 1597cdfce09SScott Long# 1607cdfce09SScott Longprompt_yesno() { 1617cdfce09SScott Long # The argument is required 162ce1794a8SMax Khon [ -n "$1" ] && msg="$1" || return 1637cdfce09SScott Long 1647cdfce09SScott Long while : ; do 165ce1794a8SMax Khon echo -n "$msg" 1667cdfce09SScott Long read _ans 1677cdfce09SScott Long case $_ans in 1687cdfce09SScott Long [Nn][Oo]|[Nn]) 1697cdfce09SScott Long return 1 1707cdfce09SScott Long ;; 1717cdfce09SScott Long [Yy][Ee][Ss]|[Yy][Ee]|[Yy]) 1727cdfce09SScott Long return 0 1737cdfce09SScott Long ;; 1747cdfce09SScott Long *) 1757cdfce09SScott Long ;; 1767cdfce09SScott Long esac 1777cdfce09SScott Long done 1787cdfce09SScott Long} 1797cdfce09SScott Long 1807cdfce09SScott Long# show_usage 1817cdfce09SScott Long# (no arguments) 1827cdfce09SScott Long# Display usage message. 1837cdfce09SScott Long# 1847cdfce09SScott Longshow_usage() { 1857cdfce09SScott Long echo "usage: ${THISCMD} [-y] [-f file] [user ...]" 1867cdfce09SScott Long echo " if the -y switch is used, either the -f switch or" 1877cdfce09SScott Long echo " one or more user names must be given" 1887cdfce09SScott Long} 1897cdfce09SScott Long 1907cdfce09SScott Long#### END SUBROUTINE DEFENITION #### 1917cdfce09SScott Long 1927cdfce09SScott Longffile= 1937cdfce09SScott Longfflag= 1947cdfce09SScott Longprocowner= 1957cdfce09SScott Longpw_rswitch= 1967cdfce09SScott Longuserlist= 1977cdfce09SScott Longyflag= 1987cdfce09SScott Long 1997cdfce09SScott Longprocowner=`/usr/bin/id -u` 2007cdfce09SScott Longif [ "$procowner" != "0" ]; then 2017cdfce09SScott Long err 'you must be root (0) to use this utility.' 2027cdfce09SScott Long exit 1 2037cdfce09SScott Longfi 2047cdfce09SScott Long 2057cdfce09SScott Longargs=`getopt 2>/dev/null yf: $*` 2067cdfce09SScott Longif [ "$?" != "0" ]; then 2077cdfce09SScott Long show_usage 2087cdfce09SScott Long exit 1 2097cdfce09SScott Longfi 2107cdfce09SScott Longset -- $args 2117cdfce09SScott Longfor _switch ; do 2127cdfce09SScott Long case $_switch in 2137cdfce09SScott Long -y) 2147cdfce09SScott Long yflag=1 2157cdfce09SScott Long shift 2167cdfce09SScott Long ;; 2177cdfce09SScott Long -f) 2187cdfce09SScott Long fflag=1 2197cdfce09SScott Long ffile="$2" 2207cdfce09SScott Long shift; shift 2217cdfce09SScott Long ;; 2227cdfce09SScott Long --) 2237cdfce09SScott Long shift 2247cdfce09SScott Long break 2257cdfce09SScott Long ;; 2267cdfce09SScott Long esac 2277cdfce09SScott Longdone 2287cdfce09SScott Long 2297cdfce09SScott Long# Get user names from a file if the -f switch was used. Otherwise, 2307cdfce09SScott Long# get them from the commandline arguments. If we're getting it 2317cdfce09SScott Long# from a file, the file must be owned by and writable only by root. 2327cdfce09SScott Long# 2337cdfce09SScott Longif [ $fflag ]; then 2347cdfce09SScott Long _insecure=`find $ffile ! -user 0 -or -perm +0022` 2357cdfce09SScott Long if [ -n "$_insecure" ]; then 2367cdfce09SScott Long err "file ($ffile) must be owned by and writeable only by root." 2377cdfce09SScott Long exit 1 2387cdfce09SScott Long fi 2397cdfce09SScott Long if [ -r "$ffile" ]; then 2407cdfce09SScott Long userlist=`cat $ffile | while read _user _junk ; do 2417cdfce09SScott Long case $_user in 2427cdfce09SScott Long \#*|'') 2437cdfce09SScott Long ;; 2447cdfce09SScott Long *) 2457cdfce09SScott Long echo -n "$userlist $_user" 2467cdfce09SScott Long ;; 2477cdfce09SScott Long esac 2487cdfce09SScott Long done` 2497cdfce09SScott Long fi 2507cdfce09SScott Longelse 2517cdfce09SScott Long while [ $1 ] ; do 2527cdfce09SScott Long userlist="$userlist $1" 2537cdfce09SScott Long shift 2547cdfce09SScott Long done 2557cdfce09SScott Longfi 2567cdfce09SScott Long 2577cdfce09SScott Long# If the -y or -f switch has been used and the list of users to remove 2587cdfce09SScott Long# is empty it is a fatal error. Otherwise, prompt the user for a list 2597cdfce09SScott Long# of one or more user names. 2607cdfce09SScott Long# 2617cdfce09SScott Longif [ ! "$userlist" ]; then 2627cdfce09SScott Long if [ $fflag ]; then 2637cdfce09SScott Long err "($ffile) does not exist or does not contain any user names." 2647cdfce09SScott Long exit 1 2657cdfce09SScott Long elif [ $yflag ]; then 2667cdfce09SScott Long show_usage 2677cdfce09SScott Long exit 1 2687cdfce09SScott Long else 2697cdfce09SScott Long echo -n "Please enter one or more user name's: " 2707cdfce09SScott Long read userlist 2717cdfce09SScott Long fi 2727cdfce09SScott Longfi 2737cdfce09SScott Long 2747cdfce09SScott Long_user= 2757cdfce09SScott Long_uid= 2767cdfce09SScott Longfor _user in $userlist ; do 2777cdfce09SScott Long # Make sure the name exists in the passwd database and that it 2787cdfce09SScott Long # does not have a uid of 0 2797cdfce09SScott Long # 2807cdfce09SScott Long userrec=`pw 2>/dev/null usershow -n $_user` 2817cdfce09SScott Long if [ "$?" != "0" ]; then 2827cdfce09SScott Long err "user ($_user) does not exist in the password database." 2837cdfce09SScott Long continue 2847cdfce09SScott Long fi 2857cdfce09SScott Long _uid=`echo $userrec | awk -F: '{print $3}'` 2867cdfce09SScott Long if [ "$_uid" = "0" ]; then 2877cdfce09SScott Long err "user ($_user) has uid 0. You may not remove this user." 2887cdfce09SScott Long continue 2897cdfce09SScott Long fi 2907cdfce09SScott Long 2917cdfce09SScott Long # If the -y switch was not used ask for confirmation to remove the 2927cdfce09SScott Long # user and home directory. 2937cdfce09SScott Long # 2947cdfce09SScott Long if [ -z "$yflag" ]; then 2957cdfce09SScott Long echo "Matching password entry:" 2967cdfce09SScott Long echo 2977cdfce09SScott Long echo $userrec 2987cdfce09SScott Long echo 2997cdfce09SScott Long if ! prompt_yesno "Is this the entry you wish to remove? " ; then 3007cdfce09SScott Long continue 3017cdfce09SScott Long fi 3027cdfce09SScott Long _homedir=`echo $userrec | awk -F: '{print $9}'` 303ce1794a8SMax Khon if prompt_yesno "Remove user's home directory ($_homedir)? "; then 3047cdfce09SScott Long pw_rswitch="-r" 3057cdfce09SScott Long fi 3067cdfce09SScott Long else 3077cdfce09SScott Long pw_rswitch="-r" 3087cdfce09SScott Long fi 3097cdfce09SScott Long 3107cdfce09SScott Long # Disable any further attempts to log into this account 3117cdfce09SScott Long pw 2>/dev/null lock $_user 3127cdfce09SScott Long 3137cdfce09SScott Long # Remove crontab, mail spool, etc. Then obliterate the user from 3147cdfce09SScott Long # the passwd and group database. 3157cdfce09SScott Long rm_crontab $_user 3167cdfce09SScott Long rm_at_jobs $_user 3177cdfce09SScott Long kill_procs $_user 3187cdfce09SScott Long rm_mail $_user 3197cdfce09SScott Long rm_files $_user 3207cdfce09SScott Long rm_user $_user 3217cdfce09SScott Longdone 322