: #	@(#)rmuser	1.5	improved account remover
# rmuser:
#	Rudimentary procedure for removing old accounts.  
# Authors:  Laura Elsaessar?, FJC, circa 1984, modified numerous times 
#	since by unknown lists of programmers.
# Modifications:
# 2/17/89, Larry Bamford.  Added locks to help ensure integrity
#	of passwd and group files.
# 8/9/90, Larry Bamford.  Removed all references to deadly cleanup 
#	routine.  Added option for SA to run ppurge in background.
#	ppurge is relatively non-destructive, but effective.
# 10/3/90, Larry Bamford.  Generalized for 386 systems.
# 10/17/91, Larry Bamford.  Changed final message from "removed" to
#	"deactivated" for consistency.
# 3/19/92, Larry Bamford.  Set umask to prevent unreadable passwd and
#	group files created by SAs with tight umasks (e.g., 066).

SA=${LOGNAME:-admin}	# recipient of ppurge output mailings
CMD=$0
HITLIST=$*
#echo REMEMBER TO CHANGE PATH AND DIR OF $CMD BEFORE INSTALLING
#PATH=.:/adm:/bin:/etc:/usr/bin export PATH	# for testing
#PATH=/adm:/bin:/etc:/usr/bin export PATH	# for safety
PATH=/bin:/etc:/usr/bin:/adm export PATH	# for security
export PATH
umask 022	# make sure new passwd and group perms are -rw-r--r--

# shell proc to remove a user
ETC=${ETC:-/etc}	# for easier debugging
ADM=${ADM:-/adm}
PASSWD=$ETC/passwd
OPASSWD=$ETC/opasswd
GROUP=$ETC/group
OGROUP=$ETC/ogroup
TMP=/tmp/$$t
TMP2=$ETC/$$t2	# same file system as /etc/passwd and /etc/group
PLOCK=$ETC/ptmp		# respected by other passwd-modifying programs
GLOCK=$ETC/gtmp		# respected by other group-modifying programs
ADDLOCK=$ETC/addLOCK	# respected by rmuser, adduser, modgrp, etc.
TMPFILES="$TMP $TMP2"

# Various CONSTANT error messages
PLOCKFAILED="
$0: Could not create lock file ($PLOCK).  
Somebody else probably updating $ETC/passwd.  Try again later.
"
GLOCKFAILED="
$CMD: Could not create lock file ($GLOCK).  
Somebody else probably updating $ETC/group.  Try again later.
"
ALOCKFAILED="
$CMD: Could not create lock file ($ADDLOCK).  
Somebody else probably using $CMD.  Try again later.
"

USAGE="
Usage:  $CMD username [username ...]

Changes each given users' account name in ${ETC}/passwd to Ousername.
Changes the encrypted password field to *nologin*.  Removes the given
user(s) from ${ETC}/group.  Offers an opportunity to invoke the ppurge
program, if it exists, in the background to deal with user's leftover
files.  (See also ppurge -?  output).  
"

set -- `getopt h\? $*`
if test $? != 0
then
	echo "$USAGE"
	exit 2
fi
for i in $*
do case $i in
	-[h\?])	echo "$USAGE"; exit 0;;
	--)	shift; break;;
	-*)	echo "$USAGE"; exit 1;;
	esac
done
if test $# -lt 1
then
	echo "$USAGE"
	exit 3
fi

# Default cleanup routine:  leaves all existing locks alone.
trap "echo \"\nInterrupted!\n\"; false; . leavelocks" 1 2 3 15

#echo "REMEMBER TO RESTORE PRIVILEGE CHECKING IN $CMD"
if test "`id | grep -c -v 'uid=0('`" -eq 1
then # am not superuser
	echo "$CMD: Only super-user or admin may run this program."
	false; . leavelocks
fi

# Create a lock that is respected by other copies of this program.
# Note that not even root can mkdir over an existing file!
#echo REMEMBER TO RESTORE LOCKING REQUIREMENTS IN $CMD
#echo "$CMD:  Locking $CMD, etc..."	# verbosity
setlock $ADDLOCK "$ALOCKFAILED" || 
    { false; . leavelocks; }	# do or die

# If interrupted, remove the lock we created.
trap "echo \"\nInterrupted!\n\"; false; . rmaddlock" 1 2 3 15

# Loop for all users on command line.
for USERTOGO in $HITLIST
do

# do we know about this user at all, if so do it, if not exit
STATUS=`egrep "^$USERTOGO:" $PASSWD` 
if test "X$STATUS" = "X"
then
	echo "$CMD:  $USERTOGO is not in the passwd file."
	echo "$CMD:  No action taken."
	continue
fi

echo "\nAre you sure you want to deactivate user \"$USERTOGO\" ? (y/n)"
read ANSWER
if test "X$ANSWER" != "Xy"
then
	echo "$CMD:  No action taken on user \"$USERTOGO\"."
	continue
fi

# make up a sed script to delete the user from /etc/group
echo s/,$USERTOGO\$//>$TMP	# last user in a group
echo s/,$USERTOGO,/,/>>$TMP	# middle user in a group
echo s/:$USERTOGO,/:/>>$TMP	# first user in a group
echo s/:$USERTOGO\$/:/>>$TMP	# only user in a group

echo "Deleting $USERTOGO from groups in $GROUP..."

# Create a lock that is respected by other programs which modify
# /etc/group.  Note that not even root can mkdir over an existing file!
#echo REMEMBER TO RESTORE LOCKING REQUIREMENT IN $0
#echo "Locking $ETC/group..."	# verbosity
setlock $GLOCK "$GLOCKFAILED" || { false; . rmaddlock; } # do or die

# Suppress interruptions.
trap "" 1 2 3 15

# Edit and replace the group file.
rm -f $OGROUP
cp $GROUP $OGROUP	# precautionary
sed -f $TMP $GROUP > $TMP2
ln $TMP2 $GROUP && rm -f $TMP2
chmod 644 $GROUP

# Remove lock file for /etc/group.
#echo "Removing lock on $ETC/group..."	# verbosity
rmlock $GLOCK || echo "WARNING!  Could not remove lock for $ETC/group!"

# Return to reasonable treatment of interrupts:  remove our lock.
trap "echo \"\nInterrupted!\n\"; { false; . rmaddlock; }" 1 2 3 15

echo "Deactivating $USERTOGO in $PASSWD..."

if test `uname -a | grep -c ' 3.2 '` = 1
then
	# SVR3.2 has commands to do it the easy way.
	passwd -l $USERTOGO
	passmgmt -m -l O$USERTOGO $USERTOGO
else
	# Create a lock that is respected by all other programs which modify
	# /etc/passwd.  Note that not even root can mkdir over an existing file!
	#echo REMEMBER TO RESTORE LOCKING REQUIREMENT IN $CMD
	#echo "$CMD:  Locking $ETC/passwd..."	# verbosity
	setlock $PLOCK "$PLOCKFAILED" || { false; . rmaddlock; } # do or die

	# Suppress interruptions.
	trap "" 1 2 3 15

	# Edit and replace the passwd file.
	rm -f $OPASSWD
	cp $PASSWD $OPASSWD	# precautionary
	awk -F: '
		{ OFS = ":" }
		$1 == "'$USERTOGO'" {
			$1 = "O'$USERTOGO'" 
			$2 = "*nologin*"
		}
		{ print }
	' $PASSWD > $TMP2 || {
		echo "$PASSWD editing failed, quitting!" 1>&2
		false; . leavelocks	# exits
	}
	ln $TMP2 $PASSWD	# quickest possible substitution
	if test $? -eq 0
	then
		rm $TMP2 || echo "$CMD:  Couldn't remove $TMP2!"
	else
		echo "$CMD: link to $PASSWD failed!"
		false; . leavelocks	# exits
	fi

	# Release passwd file.
	#echo "$CMD:  Unlocking $ETC/passwd..."	# verbosity
	rmlock $PLOCK || echo "Warning!  Could not remove $PLOCK"
fi

# Return to reasonable treatment of interrupts:  remove our lock.
trap "echo \"\nInterrupted!\n\"; false; . rmaddlock" 1 2 3 15

# If ppurge exists, ask operator whether to kick off a ppurge process 
# to begin cleaning system of the old user's files.
if test -f ${ADM}/ppurge
then
PROMPT="
Do you wish to initiate ppurge in the background to move all 
${USERTOGO}'s files to purgatory on their respective file systems?  
ppurge can be started by hand later, if you choose not to do so now.

(Answer Y or N, RETURN for default NO, ? for more info on ppurge):"
RESPONSE=
while test "$RESPONSE" = ""
do
	echo "$PROMPT"
	read RESPONSE
	case "$RESPONSE" in
	Y*|y*)
		echo "ppurging ${USERTOGO}'s files in the background..."
		# Suppress interruptions in child processes.
		trap "" 1 2 3 
		nohup ${ADM}/ppurge O$USERTOGO 2>&1 | 
		nohup mail $SA &
		# Restore previous treatment of interrupts.
		trap "echo \"\nInterrupted!\n\"; false; . rmaddlock" 1 2 3 
		PPURGE=started
		;;
	""|N*|n*)
		PPURGE=notstarted
		echo "Remember, you can initiate ppurge later by typing"
		echo "nohup ${ADM}/ppurge O$USERTOGO 2>&1 | mail yourself &"
		echo "\nPress RETURN when finished reading...\c"
		read RESPONSE
		RESPONSE=ok	# exit loop
		;;
	\?)
		${ADM}/ppurge -?
		echo "Press RETURN when ready to decide...\c"
		read RESPONSE
		RESPONSE=
		;;
	!)
		echo "Remember to type ctl-D to return to the menu."
		${SHELL:-/bin/sh}
		echo !
		RESPONSE=
		;;
	!*)
		_CMD=`echo $RESPONSE | cut -c2-256`
		${SHELL:-/bin/sh} -c "$_CMD"
		echo !
		echo Press RETURN to continue...
		read RESPONSE
		RESPONSE=
		continue
		;;
	*)
		echo "Please answer Y or N"
		RESPONSE=
		;;
	esac
done
fi # if ppurge exists

echo "User \"$USERTOGO\" deactivated"
if test -f ${ADM}/ppurge 
then
	if test "$PPURGE" = "started"
	then
		PPURGEMSG="
Most of ${USERTOGO}'s files will eventually show up in purgatory
directories under the root directories of all the file systems.  These
files should be archived and removed in a few days.  Files that remain
in the system are probably directories that contain other users'
files, and so cannot yet be removed.
"
		echo "$PPURGEMSG"
	fi
fi

done # loop for all users listed on command line

# Update pwcopy, if it exists.
for dir in /adm /usr
do
	if test -f ${dir}/security/other/pwcopy
	then
		echo "updating audit copy of /etc/passwd ..."
		cd ${dir}/security/other
		mv pwcopy pwcopy.bak 2>/dev/null || 
		    { echo "Can't mv pwcopy pwcopy.bak"; break; }
		./pwgross 2>/dev/null ||
		    { echo "Can't ./pwgross 2>/dev/null"; break; }
		break
	fi
done

#echo "$CMD:  Unlocking $CMD, etc..."	# verbosity
true; . rmaddlock
