#!/bin/ksh
#
# ident "@(#)bbmkuser.sh 1.6     01/05/30 SMI"
#
# Copyright (c) 2000 by Sun Microsystems, Inc.
# All rights reserved.
#

. $BBROOT/etc/opt/SUNWbb/blackbox.rc

# init some variables
prefix=""
start=""
count=""
selection=""  

usage() {
	me=`basename $0`
	echo "usage: $me"
	echo "       $me -c <prefix> <first> <count>"
	echo "       $me -m <prefix> <first> <count>"
	echo "       $me -d"	
	echo "       $me -t"
	echo "       $me -r"
	echo "       $me -s"
	echo "       without any arguments $me prints the current confiruration"
        echo "       -c creates <count> user entries, starting at uid <first>"
	echo "          of the form <prefix><number>, where 0 <= number < count"
        echo "       -m moves the range of uids, it does a delete followed by create" 
	echo "       -d delete the currently configured uids"
	echo "       -t test for any ControlledAccessUser from prior config"
	echo "       -r force a removal of users listed by -t option"
	echo "       -s status, prints number of configured and currently"
	echo "          used users"
	echo "       The permitable ranges for the arguments are:"
	echo "       prefix - up to four characters"
	echo "       first  - any value > 100"
	echo "       count  - >= 1" 
	exit 1
}

#
# copy the relevant content into the chroot environment
#
copy_users() {

	cuprefix=$1
	cucount=$2

	rm -f $BBROOTPATH/etc/passwd
	rm -f $BBROOTPATH/etc/shadow

	if [ $# = 0 ]; then 
		touch $BBROOTPATH/etc/passwd
                touch $BBROOTPATH/etc/shadow 
	else

		cucnt=0;
		while [ $cucnt -lt $cucount ]; do
			cuname=${cuprefix}${cucnt}
			nawk -F':' -v N=$cuname '{
                        	if ( $1 == N ) 
					printf("%s:%s:%s:%s:%s:/home/%s:%s\n",
						$1,$2,$3,$4,$5,$1,$7 ); 
			}' /etc/passwd >> $BBROOTPATH/etc/passwd
			nawk -F':' -v N=$cuname '{
                                if ( $1 == N )
                                        print $0
                        }' /etc/shadow >> $BBROOTPATH/etc/shadow
			(( cucnt+=1 ))
		done
	fi
}

#
# check the current configurtion against the stale list
# and update accordingly
# $1 - egrep string for currently configured users
#
check_configured() {

	# Extract all users from /etc/passwd which are not in
	# the configured range of users <prefix>n 0<=n<count
	# but do use the ControlledAccessUser comment field.
	# All users which match $BBUSERCOMMENT, but do not belong
	# to the current range of configured users appear to be left over
	# from earlier CAM configurations.
	if [ "$prefix" != "" ]; then
		nawk -F':' -v C=$BBUSERCOMMENT -v P=$prefix -v R=$count '{
                	if ( C == $5 ) {
				if ( match( $1, P ) == 1 ) {
                                	len=length(P);
                                	num=substr($1,len+1);
                                	inum=int(num);
                                	if ( match(num,/[0-9]+/) != 1 ||
                                     	inum < 0 || inum >= int(R) )
                                        	print $1 
                       		} else {
					print $1
				}
			}
		}' /etc/passwd > $BBUSERLIST.tmp_check	
	else
		nawk -F':' -v C=$BBUSERCOMMENT '{ 
			if ( C == $5 ) { 
				print $1
			}
		}' /etc/passwd > $BBUSERLIST.tmp_check
	fi
        length=`wc -c $BBUSERLIST.tmp_check | awk '{ print $1 }'`
        if [ $length = 0 ]; then
                rm -f $BBUSERLIST
        else
                mv $BBUSERLIST.tmp_check $BBUSERLIST
	fi
}

#
# kill all processes of this user
# $1 user
#
kill_all_procs() {

	/bin/ps -e -o "user,pid" | nawk -v U=$1 '{
               
		if ( $1 == U ) 
			system( "kill -9 "$2 ) 
	}' 
}

#
# delete a user from /etc/passwd, remove home dir
# $1 - user to delete
# return exit code of userdel
#
do_userdel() {

	homedir=`nawk -F':' -v U=$1 '{
		if ( $1 == U ) 
			print $6
	}' /etc/passwd`

	if [ -d $homedir ]; then
		/usr/sbin/userdel -r $1 2>/dev/null
		res=$?
	else
		/usr/sbin/userdel $1 2>/dev/null
                res=$?           
	fi
	return $res
}

# 
# create a range of users in /etc/passwd 
# $1 user name prefix
# $2 first uid to use
# $3 number of users to create
# return code: 0  ok
# return code: 11 partially failed
# return code: 12 failed, no user created and no user conf file written
#
# if we try to configure a user which didn't delete last time, then
# that user will be in BBUSERLIST. We need to check that and remove it
# from the list, since the entry in passwd might have gone by now (manual
# delete) and it is a valid user again.
#
create_users() {

	res=0
	uid=$2
	cnt=0

	while [ $cnt != $3 ]; do
	
        	user=${1}$cnt
        	home=$BBCHRHOME/$user
        	/usr/sbin/useradd -u $uid -g $BBUSERGRP -c $BBUSERCOMMENT \
			-s $SHELL -d $home $user 2>/dev/null
		if [ $? != 0 ]; then
			echo "passwd entry for $user failed"
			res=11
			break;
		fi
		print -n "."
        	(( uid+=1 ))
        	(( cnt+=1 ))
	done
	print
	if [ $cnt != 0 ]; then
		echo "$1 $2 $cnt" > $BBMAXUSERFILE    
		chmod 644 $BBMAXUSERFILE
		echo "$cnt users configured"

		check_configured
		copy_users $1 $cnt
	else
		echo "no users configured"
		res=12
	fi
	return $res
}

#
# deletes a range of users from /etc/passwd
# $1 user name prefix
# $2 first uid to use
# $3 number of users to delete
# return code: 0  ok
# return code: 21 removing of users partially failed
#
delete_users() {

	res=0
        cnt=0
	rmv=0
	prefix=$1
	start=$2
	count=$3

	# first disable access by renaming $BBMAXUSERFILE
	mv $BBMAXUSERFILE $BBMAXUSERFILE.do_delete
	
	# remove old tmp user list
	rm -f $BBUSERLIST.tmp_delete

        while [ $cnt != $count ]; do

                user=${prefix}$cnt
		name=`nawk -F':' -v U=$user '{ 
			if ( U == $1 ) 
				print $5 
		}' /etc/passwd`
		if [ "$name" = "$BBUSERCOMMENT" ]; then

			# kill all processes of the user first
			# tbd

                	do_userdel $user
                	if [ $? != 0 ]; then
				print
                        	print "removing passwd entry failed for $user"
				print $user >> $BBUSERLIST.tmp_delete
				res=21
			else
				(( rmv+=1 ))
				print -n "."
			fi
		else
			echo "passwd entry for $user does not match: $BBUSERCOMMENT, ignored.."
		fi
                (( cnt+=1 ))
        done
	print
	rm -f $BBMAXUSERFILE.do_delete
	if [ -f $BBUSERLIST.tmp_delete ]; then
		print "delete failed for the following users:"
		cat $BBUSERLIST.tmp_delete
		print "use -r option to remove"
	fi
 
	echo "$rmv of $count users deleted"
	copy_users 
	return $res
}

#
# moves a range of users in /etc/passwd
# $1 current user prefix
# $2 current uid start
# $3 current count
# $4 user name prefix
# $5 first uid to use
# $6 number of users to create
# return code: 0  ok
# return code: 1X 2X return codes from create or delete
#
move_users() { 

	res=0
	delete_users $1 $2 $3
	res=$?
	if [ $? = 0 ]; then
		create_users $4 $5 $6
		res=$?
	else
		echo "failed to delete current user range"
	fi
	return $res
}

#
# test for users in /etc/passwd left over from earlier configurations
# return code: 0  no stale users found
# return code: 31 stale users found
#
test_users() {

	check_configured
	res=0
	if [ -f $BBUSERLIST ]; then
		print "stale user entries:"
                cat $BBUSERLIST
		res=31
        else
		print "no enties found"
	fi
	return $res
}

#
# remove users from /etc/passwd, which have been leftover from earlier
# attempts of delete_users.
# return code: 0  removed all stale users
# return code: 41 remove partially failed
#
remove_users() {

	check_configured
	res=0
	if [ -f $BBUSERLIST ]; then

		rm -f $BBUSERLIST.tmp_remove
		for user in `cat $BBUSERLIST`; do

			kill_all_procs $user
			do_userdel $user 
                        if [ $? != 0 ]; then
                                echo "removing passwd entry failed for $user"
                                print $user >> $BBUSERLIST.tmp_remove
				res=41
			else
				print "removed: $user"
                        fi  
		done
		if [ -f $BBUSERLIST.tmp_remove ]; then
			print "failed to remove:"
			cat $BBUSERLIST.tmp_remove
		fi
	fi
	return $res
}

#
# count users currently configured and users currently being used
# $1 current user prefix
# $2 number of users configured
# return code: 0  counting was successful
# return code: 51 something went wrong
#
count_users() {

	MAXUSER=$2
	USERPREFIX=$1
	cnt=0
	used=0
	while [ $cnt != $MAXUSER ]; do 
		BBUSER=${USERPREFIX}$cnt
		BBUSERLOCK=$BBLOCKPATH/$BBUSER.lock
		if [ -f $BBUSERLOCK ]; then
			((used+=1))
		fi
		((cnt+=1))
	done
	print "$MAXUSER $used"
	return 0
}

#
# we only accept one option in the arguments
# if selection is set already, then there has been some
# other option in the arguments alreday => usage and exit
#
select_option() {
	
	if [ "$selection" = "" ]; then
        	selection=$opt;
        else
                usage
	fi
}

#
# check_args, check for acceptable ranges
# $1 user prefix
# $2 start of uids
# $3 number of uids
#
check_args() {

	if [ $# != 3 ]; then
		usage
	fi
	if [ ${#1} -gt 4 ]; then 
		usage
	fi
	if [ $2 -lt 100 ]; then 
		usage
	fi
	if [ $3 -lt 1 -o $3 -gt 9999 ]; then
		usage 
	fi
}

#
# main starts here
#
while getopts cmdrst opt; do
	case $opt in
	c)	select_option $opt
		;;
	m)	select_option $opt
		;;
	d)	select_option $opt
		;;
	r)	select_option $opt
		;;
	t)	select_option $opt
		;;
	s)	select_option $opt 
		;;
	\?)	usage
		;;
	esac
done
shift `expr $OPTIND - 1`

if [ -f $BBMAXUSERFILE ]; then
	prefix=`awk '{ print $1 }' $BBMAXUSERFILE`
	start=`awk '{ print $2 }' $BBMAXUSERFILE`
	count=`awk '{ print $3 }' $BBMAXUSERFILE`
fi
	
if [ "$selection" = "" ]; then
	# just print configuration (if any)
	if [ "$prefix" != "" ]; then
		echo "current settings:"
		echo "prefix: $prefix"
		echo "start : $start"
		echo "count : $count"
	else
		echo "not configured..."
	fi
	exit 0
fi

res=0
case $selection in
	c)	check_args $*
		if [ "$prefix" = "" ]; then
			create_users $*
			res=$?
		else
			print "already configured, use -m option"
		fi
		;;
	m)	check_args $*
		if [ "$prefix" != "" ]; then
			move_users $prefix $start $count $*
			res=$?
		else
			echo "not configured..." 
		fi
		;;
	d)	if [ $# != 0 ]; then
			usage
		fi
		if [ "$prefix" != "" ]; then
			delete_users $prefix $start $count
		        res=$?
                else
                        echo "not configured..."
                fi 
		;;
	t)	if [ $# != 0 ]; then
                        usage
                fi 
		test_users
		res=$?
		;;
	s)	if [ $# != 0 ]; then
                        usage
                fi
		if [ "$prefix" != "" ]; then
			count_users $prefix $count	
			res=$?
		else
			echo "not configured..."  
			res=1
		fi
		;;
	r)	if [ $# != 0 ]; then
                        usage
                fi 
		remove_users
		res=$?
		;;
esac

exit $res
                                    
