#!/bin/sh
# $Id: get-profile.sh,v 1.15 2004/05/29 15:37:00 lreiter Exp $
#
#	get-profile.sh:
#		Profile-based provisioning technology
#		Profile get/reconstruction script
#
#	Copyright 2003 NeTraverse, Inc.
#
#	return values:
#		0:	success
#		1:	invalid usage
#		2:	invalid user specified/cannot determine home directory
#		3:	no existing profile found, and cannot determine master
#		4:	unable to read master profile information
#		5:	specified master profile type is not master
#		6:	master profile does not contain a Windows installation
#		7:	failed to load profile information
#		8:	user script failed
#

# Print out to the log file when ok to log, and to the user when trace is on.
Log()
{
	[ "$OK_TO_LOG" = "ok_to_log" ] && echo $EPT "$*" >> "$LOGFILE"
	[ "x$TRACE" = "xtrace" ]       && echo $EPT "$*"
}

# Print out to the user, and to the log file when ok to log.
Echo()
{
	[ "$OK_TO_LOG" = "ok_to_log" ] && echo $EPT "$*" >> "$LOGFILE"
	[ "$DO_SILENT" = "notsilent" ] && echo $EPT "$*"
}

# Runs a script, logging to the log file if possible and tracing to stdout
# if possible as well; should the script return a failure code (nonzero),
# this script will exit immediately
RunScript()
{
	SCRIPTBASE=$2
	SCRIPTNAME=$1/$SCRIPTBASE
	if [ "$OK_TO_LOG" = "ok_to_log" ]; then
		SCRIPT_LOGFILE="$HOME/.merge/get-profile-$SCRIPTBASE.log"
	elif [ "x$TRACE" = "xtrace" ]; then
		SCRIPT_LOGFILE=""
	else
		SCRIPT_LOGFILE=/dev/null
	fi
	Log "\nFound $SCRIPTBASE"
	Log "Executing $SCRIPTNAME ..."
	[ "$SCRIPT_LOGFILE" != "" ] && Log "(logging to $SCRIPT_LOGFILE)"
	$SCRIPTNAME >$SCRIPT_LOGFILE 2>&1
	RETVAL=$?
	if [ "x$TRACE" = "xtrace" -a "$SCRIPT_LOGFILE" != "" ]; then
		cat $SCRIPT_LOGFILE
	fi
	[ "$OK_TO_LOG" != "ok_to_log" ] && rm -f $SCRIPT_LOGFILE
	Log "$SCRIPTBASE returned $RETVAL\n"
	if [ $RETVAL != 0 ]; then
		Log "$SCRIPTBASE failed!"
		exit 8
	fi
}

# Runs a script, if found in either the user-specific settings or default
# settings directory of the master profile
RunScriptFound()
{
	if [ -x $USERSETDIR/$1 ]; then
		RunScript $USERSETDIR $1
	elif [ -x $DEFSETDIR/$1 ]; then
		RunScript $DEFSETDIR $1
	fi
}

. /etc/mrgssv.sh

PROGNAME=`basename $0`; export PROGNAME

USERID=`$STATICMERGE/bin/print_uid`
if [ "$USERID" = "0" ]; then

# root runtime mode: figure out the home directory of the master user, then
# iterate through the list of target users and su -c this same script for each
# one, passing in the master home directory

	if [ "$1" = "" -o "$2" = "" ]; then
		echo "usage: $PROGNAME <master-username> <user1> [<user2> ...]"
		exit 1
	fi
	HOMEDIR=`su - $1 -c pwd`
	if [ "$HOMEDIR" = "" ]; then
		echo "$PROGNAME: unable to determine home directory for user $1"
		exit 2
	fi

	AGREETXT="The user agreed that NeTraverse is not responsible for his/her compliance to Microsoft licensing terms."
	AGREEFILE=$VARMERGE/agree_profile.txt

	grep "$AGREETXT" "$AGREEFILE" >/dev/null 2>&1
	if [ $? != 0 ]; then
	echo ""
	echo "You are about to make the Windows installation for the "
	echo "following user available to one or more other user accounts:"
	echo "        $1"
	echo ""
	echo "Please note that Microsoft licensing typically requires that"
	echo "you have at least one (1) Windows license per user account."
	echo "Alternatively, you may use a site license for Windows, if you "
	echo "purchased such a license.  Please review the End User License "
	echo "Agreements of both your NeTraverse and Windows products for "
	echo "additional details."
	echo ""
	echo "Please type the word yes at the prompt if you understand and"
	echo "agree that NeTraverse IS NOT RESPONSIBLE for your compliance "
	echo "with Microsoft licensing terms."
	echo ""
	echo -n "Do you agree with these terms (yes/no)? "
	read RESPONSE
	if [ "$RESPONSE" != "yes" ]; then
		echo "Aborted at user's request."
		exit 0
	else
		echo $AGREETXT >$AGREEFILE
		date >>$AGREEFILE
	fi
	echo ""
	echo "Thank you, now proceeding..."
	echo ""
	fi
	MASTERUSER=$1
	
	shift
	umask 2
	for i in $*; do
		echo "user $i..."

		# create the user setting directory
		USERSET=$HOMEDIR/.merge-profile/users/$i
		if [ ! -d $USERSET ]; then
			mkdir -p $USERSET
			chown $MASTERUSER $HOMEDIR/.merge-profile/users
			chown $MASTERUSER $USERSET
		fi

		# Create the default registry-settings file; note that we
		# will have it specify a computername regardless of whether
		# VNET is currently in use or not.  This is so that in case
		# the admin changes the master profile to VNET in the future,
		# he/she does not HAVE to edit all the computer names.
		# Note that we will set the logon name as well, unless the
		# override is set against it
		REGSET=$USERSET/registry-settings
		if [ ! -r $REGSET ]; then
			SHORTHOST=`hostname -s`
			COMPNAME=`echo $SHORTHOST-$i |cut -b 1-15`
			echo "Network.ComputerName=\"$COMPNAME\"" >$REGSET
			if [ "$MERGE_GET_PROFILE_KEEP_LOGON" != "on" ]; then
				echo "Network.username=\"$i\"" >>$REGSET
			fi
			chown $MASTERUSER $REGSET
		fi

		# kick off the non-root mode of this script
		su - $i -c "$STATICMERGE/adminbin/get-profile $HOMEDIR"
	done
	exit 0
fi

# Setup logging
[ "$SYSTEMTYPE" = "linux" ] && EPT="-e"
OK_TO_LOG="no_log"
DO_SILENT="notsilent"
LOGFILE="$HOME"/.merge/get-profile.sh.log
touch "$LOGFILE"
if [ -f "$LOGFILE" -a -w "$LOGFILE" -a ! -L "$LOGFILE" ]
then
	date > "$LOGFILE"
	OK_TO_LOG="ok_to_log"
else
	LOGFILE=/dev/null
	OK_TO_LOG="no_log"
fi

# non-root runtime mode: attempt to construct a child of the profile contained
# in the specified home directory; if no home directory is specified, we
# must be able to find an existing MERGE_PROFILE_MASTER in profile-info

cd
if [ $# = 0 ]; then
	if [ -r .merge-profile/profile-info ]; then
		. .merge-profile/profile-info
	fi
	if [ "$MERGE_PROFILE_MASTER" = "" ]; then
		Echo "$PROGNAME: no existing profile found,"
		Echo "and master home directory not specified"
		exit 3
	else
		HOMEDIR=$MERGE_PROFILE_MASTER
	fi
elif [ $# != 1 ]; then
	Echo "usage: $PROGNAME [<master-home-dir>]"
	exit 1
else
	HOMEDIR=$1
fi

PROFILEDIR=$HOMEDIR/.merge-profile
MERGEDIR=$HOMEDIR/.merge
WINDIR=$HOMEDIR/win
USERSETDIR=$HOMEDIR/.merge-profile/users/$USER
DEFSETDIR=$HOMEDIR/.merge-profile/default
MERGE_PROFILE_DIR=$PROFILEDIR; export MERGE_PROFILE_DIR
MERGE_PROFILE_HOME=$HOMEDIR; export MERGE_PROFILE_HOME
MERGE_PROFILE_WIN=$WINDIR; export MERGE_PROFILE_WIN
MERGE_PROFILE_DOTMERGE=$MERGEDIR; export MERGE_PROFILE_DOTMERGE
if [ "$TARGETCFG" = "" ]; then
	TARGETCFG="win"
fi
MERGE_PROFILE_TARGET_CFG=$TARGETCFG; export MERGE_PROFILE_TARGET_CFG
if [ "$TARGETOLD" = "" ]; then
	MERGE_PROFILE_TARGET_OLD=$HOME/win.profile-old
else
	MERGE_PROFILE_TARGET_OLD=$TARGETOLD
fi
export MERGE_PROFILE_TARGET_OLD
if [ "$TARGETDIR" = "" ]; then
	MERGE_PROFILE_TARGET_WIN=$HOME/win
else
	MERGE_PROFILE_TARGET_WIN=$TARGETDIR
fi
export MERGE_PROFILE_TARGET_WIN
MERGE_PROFILE_TARGET_DOTMERGE=$HOME/.merge; export MERGE_PROFILE_TARGET_DOTMERGE

Log "Master profile:"
Log " PROFILEDIR: $PROFILEDIR"
Log " WINDIR:     $WINDIR"
Log " MERGEDIR:   $MERGEDIR"
Log " USERSETDIR: $USERSETDIR"
Log " DEFSETDIR:  $DEFSETDIR\n"

if [ ! -r $PROFILEDIR/profile-info ]; then
	Echo "$PROGNAME: unable to read master profile info"
	exit 4
fi

. $PROFILEDIR/profile-info
if [ "$MERGE_PROFILE_TYPE" != "master" ]; then
	Echo "$PROGNAME: profile type is not master"
	exit 5
fi

if [ "$TARGETDIR" = "" ]; then
	if [ ! -f $WINDIR/windows/inf/layout.inf -o ! -d $MERGEDIR ]; then
		Echo "$PROGNAME: $HOMEDIR does not contain a Windows " \
"installation"
		exit 6
	fi
fi

# if a registry export is needed, do this *before* we move win
REGKEEP=""
REGKEEPDATA=""
if [ -r $USERSETDIR/registry-preserve ]; then
	REGKEEP="$USERSETDIR/registry-preserve"
elif [ -r $DEFSETDIR/registry-preserve ]; then
	REGKEEP="$DEFSETDIR/registry-preserve"
fi
if [ "$REGKEEP" != "" ]; then
	REGKEEPDATA="$MERGE_PROFILE_TARGET_DOTMERGE/regexport.out"
	Log "regexport -k $MERGE_PROFILE_TARGET_CFG <$REGKEEP >$REGKEEPDATA"
	"$STATICMERGE"/publicbin/regexport -k $MERGE_PROFILE_TARGET_CFG \
		<"$REGKEEP" >"$REGKEEPDATA" 2>>$LOGFILE
	Log "\n"
fi

[ -d $MERGE_PROFILE_TARGET_OLD ] && rm -rf $MERGE_PROFILE_TARGET_OLD

[ -d $MERGE_PROFILE_TARGET_WIN ] && mv $MERGE_PROFILE_TARGET_WIN \
$MERGE_PROFILE_TARGET_OLD

mkdir -p mydata/MyDocuments
	
mkdir -p .merge-profile

if [ "$TARGETDIR" = "" ]; then
	echo "MERGE_PROFILE_TYPE=\"child\"" >.merge-profile/profile-info
	echo "MERGE_PROFILE_MASTER=\"$HOMEDIR\"" >>.merge-profile/profile-info
fi

# run the user preload script, if found
mkdir -p $MERGE_PROFILE_TARGET_DOTMERGE
mkdir -p $MERGE_PROFILE_TARGET_WIN
RunScriptFound preload-script

# find any special file lists in the settings directory for this user
DASH_O=""
DASH_C=""
DASH_P=""
OMIT_FILES=""
COPY_FILES=""
KEEP_FILES=""

# the order will be such that anything in the user settings directory will
# override anything in the default settings directory
for i in $USERSETDIR $DEFSETDIR; do
	if [ "$OMIT_FILES" = "" ]; then
		OMIT_FILES="$i/omit-files"
		if [ -r $OMIT_FILES ]; then
			DASH_O="-o"
		else
			OMIT_FILES=""
		fi
	fi
	if [ "$COPY_FILES" = "" ]; then
		COPY_FILES="$i/copy-files"
		if [ -r $COPY_FILES ]; then
			DASH_C="-c"
		else
			COPY_FILES=""
		fi
	fi
	if [ "$KEEP_FILES" = "" ]; then
		KEEP_FILES="$i/preserve-files"
		if [ -r $KEEP_FILES ]; then
			DASH_P="-p"
		else
			KEEP_FILES=""
		fi
	fi
done

if [ -d $MERGE_PROFILE_TARGET_OLD ]; then
	DASH_OLD="-O"
	OLD_DIR="$MERGE_PROFILE_TARGET_OLD"
else
	DASH_OLD=""
	OLD_DIR=""
	DASH_P=""
	KEEP_FILES=""
fi

# load the profile
cp -fdpR $MERGEDIR/* .merge
cd $MERGE_PROFILE_TARGET_WIN
CMD="$STATICMERGE/adminbin/profile-load $DASH_OLD $OLD_DIR $DASH_O $OMIT_FILES \
$DASH_C $COPY_FILES $DASH_P $KEEP_FILES $WINDIR"
INPUTFILE="$PROFILEDIR/profile-meta"
Log "running:"
Log "$CMD <$INPUTFILE"
$CMD <$INPUTFILE >>$LOGFILE 2>&1
if [ $? != 0 ]; then
	exit 7
fi
cd ..

# Import anything the user wanted preserved from the registry
if [ "$REGKEEPDATA" != "" ]; then
	Log "\nImporting $REGKEEPDATA"
	cat "$REGKEEPDATA" | "$STATICMERGE"/publicbin/regedit -k $TARGETCFG - \
		>>$LOGFILE 2>&1
fi

# Fix the registry
IMPORTFILE=""
if [ -r $USERSETDIR/registry-settings ]; then

	# run the settings through settings2reg, and pipe into regedit
	Log "\nImporting $USERSETDIR/registry-settings"
	$STATICMERGE/adminbin/settings2reg $USERSETDIR/registry-settings \
		| $STATICMERGE/publicbin/regedit -k $TARGETCFG - >>$LOGFILE 2>&1
fi
if [ -r $USERSETDIR/registry-import ]; then
	IMPORTFILE=$USERSETDIR/registry-import
elif [ -r .merge-profile/registry-import -a ! -d $USERSETDIR ]; then
	
	# let the local user registry-import work only for backwards
	# compatibility with some early releases; if we even find the newer-
	# style user settings directory, we don't even get here since the
	# account was provisioned using the newer tools
	IMPORTFILE=.merge-profile/registry-import
fi

if [ "$IMPORTFILE" != "" ]; then

	# something to import as is; do it
	Log "\nImporting $IMPORTFILE"
	cat $IMPORTFILE | $STATICMERGE/publicbin/regedit -k $TARGETCFG - \
		>>$LOGFILE 2>&1
fi

# run the user postload script, if found
cd
RunScriptFound postload-script

exit 0
