#!/bin/bash
##
##------------------------------------------------------------------------------
##	NORMALIZZAZIONE UTENTI E GrUPPI
##------------------------------------------------------------------------------
##
## Crea o aggiorna gli utenti LOCALI sul sistema normalizzandoli secondo
## una definizione standardizzata.
##
##------------------------------------------------------------------------------

set -u


nss_disable()
{
	# per prima cosa tolgo di mezzo /etc/nsswitch.conf, per
	# impedire interferenze con sistemi esterni tipo LDAP o
	# Kerberos. Il file viene rinominato (in questo modo le
	# librerie lavorano con lo standard, che e` locale), e
	# recuperato al termine tramite la funzione nss_cleanup()
	#
	# la stessa cosa vale per quel fetuso di nscd, che mantiene
	# in cache le info prese da ldap anche dopo che il file
	# /etc/nsswitch.conf viene rinominato (pessimo che non abbia
	# un controllo su questo file)
	#
	# e` tuttavia possibile invalidare la cache (vedi restart successivo)
	#
	[ -f /etc/nsswitch.conf ] && {
		mv /etc/nsswitch.conf /etc/nsswitch.conf.offline || exit 1
	}
	NSCD_WAS_RUNNING=false
	[ -f /etc/init.d/nscd ] && {
		[ "`ps axuwww | grep "/sbin/nscd" | grep -v grep`" ] && {
			sh /etc/init.d/nscd stop || :
			NSCD_WAS_RUNNING=true
		}
	}
}


nss_cleanup()
{
	[ -f /etc/nsswitch.conf.offline ] && {
		mv /etc/nsswitch.conf.offline /etc/nsswitch.conf || exit 1
	}
	$NSCD_WAS_RUNNING && {
		sh /etc/init.d/nscd start
		nscd --invalidate passwd
		nscd --invalidate group
	}
}

usage()
{
	echo "
usage: $CMD [options]

options:
  -n|--dry-run	test only
  -r|--retry N	set retry count to N (now: $RETRY)
  -v|--verbose	set verbose mode
" >&2
	exit 1
}


# (MAIN)

CMD=`basename $0`
DUMMY=
RETRY=10
VERBOSE=true

# add local dir to searchpath
export PATH=`pwd`:$PATH

NORM_USERS_CMD="./normalize-users"
NORM_GROUPS_CMD="./normalize-groups"


while [ $# != 0 ]
do
	case "$1" in
		-\?|--help|"")	usage ;;
		-n|--dry-run)	DUMMY=-n ;;
		-v|--verbose)	VERBOSE=true ;;
		-r|--retry)	shift
				[ "$1" -lt 1 -o "$1" -gt 99 ] && usage
				RETRY=$1
				;;
		-*) usage ;;
	esac
	shift
done


nss_disable

[ -x pre-delete.sh ] && {
	sh pre-delete.sh $DUMMY || exit $?
}


# il file standard_groups viene passato as-is al
# comando normalize-groups, viene solo ordinato in ordine
# decrescente di numero in modo da limitare le
# possibili collisioni in caso di rename di gid
#
rm -f tmp.tmp
for file in standard_groups local_groups
do
	[ -f $file ] && {
		sed -e 's/ *#.*//' -e '/^ *$/d' $file >> tmp.tmp
	}
done
echo " * checking groups ..."
$NORM_GROUPS_CMD $DUMMY -r $RETRY `sort -g -r tmp.tmp` || {
	nss_cleanup
	exit 1
}
rm -f tmp.tmp


# il file standard_users invece viene letto riga per
# riga (eliminando eventuali commenti), perche` contiene
# come primo token il tipo di utente e nei successivi
# uno o piu` utenti
#
files=
for file in standard_users local_users
do
	[ -f $file ] && files="$files $file"
done
classes=
for file in local_users_classes users_classes
do
	[ -f $file ] && classes="$classes -c $file"
done

[ "$files" != "" -a "$classes" != "" ] && {
	echo " * checking users ..."

	for retry in 1 2 3
	do
		status=0
		for class in `sed -e 's/ *#.*//' -e '/^ *$/d' -e 's/[ ,	].*//' $files | sort -u`
		do
			cat $files | while read fileclass users
			do
				[ "$fileclass" = "$class" ] && echo "$users"
			done | sort -g -r >sort.tmp
			$VERBOSE && echo "   class: $class ..."
			$NORM_USERS_CMD $DUMMY -r 1 $classes $class `cat sort.tmp`
			[ $? != 0 ] && status=1
		done
		[ $status = 0 ] && break
		echo -e "\n  ... (retry $retry) ..."
	done
	[ $status != 0 ] && {
		echo -e "  error updating users"
		nss_cleanup
		exit 1
	}
	rm -f sort.tmp
}

nss_cleanup

exit 0
