#!/bin/sh
#	Copyright (c) 1992 Dynamic Software AB,	All Rights Reserved
#
#	Dynamic Software AB, DynaSoft
#
#
# Backup/Restore of BoKS programs, database and logs.
# Change backup/restore programs as nessesary.
#
# The scripts is called from "boksadm" as 
#
# 1. Backup of BoKS programs and database: boks_bru -b -d <device>
# 2. Restore of BoKS programs and database: boks_bru -r -d <device>
# 3. Move logs to backup media: boks_bru -m -d <device>
# 4. Restore logs from backup media: boks_bru -e -d <device>
# 5. Show contents of backup media: boks_bru -s -d <device>
#

for f in /etc/opt/SUNWssmi/ENV /etc/boksenv; do
    if [ -f $f ]; then
        eval `grep '^BOKS_lib=' $f`
        PATH="$BOKS_lib:$PATH"
	export PATH
        break
    fi
done

# Get BoKS locations
for d in DIR etc sbin lib  data tmp var; do
    eval BOKS_$d="`boksdir $d`"
    export BOKS_$d
done
test -z "$BOKS_lib" && { echo "Must be run in a BoKS environment" >&2; exit 1; }
PATH="$BOKS_lib:$BOKS_sbin:$BOKS_bin:$PATH"; export PATH


#
# Find out the name of the Logg Directory
#
getlogdir()
{
    LOGDIR=`logadm -D b`
    if [ -z "$LOGDIR" ]; then
	LOGDIR=$BOKS_data
    fi
}


setboksenv() {
    eval "$1='`grep \"$1=\" $BOKS_etc/ENV  2>/dev/null | sed 's/.*=\(.*\)/\1/'`'"
}

# Read/Write Stdin to/from device $2
#
# If device is character special, data will be padded by
# "newline" characters to make it fit on an even 512 byte boundary 
# Writing will then be done using "dd" with a blocksize of 10k byte.
#
# The padding is currently done by the awful awk-script below, which
# will only work as long as the output contains JUST PLAIN TEXT!
dd_device() {
	dev="$2"
	blocksize=10k

	if [ $1 = Write ] ; then
		#
		# Write to device
		if [ -c $dev ]; then
			awk '{
				sum+=length($(0))+1;
				print
			}
			END{for (i=(512-sum%512);i>0;i--){printf "\n"}}' \
				| dd of=$dev obs=$blocksize
		else
			#
			# Set file creation mask to restrict the file mode of 
			# the outfile
			rm -f $dev
			umask 077
			cat > $dev
		fi
	else
		#
		# Read from device
		if [ -c $dev ]; then
			dd if=$dev ibs=$blocksize || echo false
		else
			cat $dev || echo false
		fi
	fi
}

# If there are certificates stored below $BOKS_data/sso_creds,
# import them into the database. Note that the BoKS daemons
# must be running for this to work.
#
certs2db () {
    find $BOKS_data/sso_creds/ca_creds/certs $BOKS_data/sso_creds/user_creds/certs $BOKS_data/sso_creds/user_creds/keypkgs -type f -exec $BOKS_lib/certfile2db {} \;
}

# Convert a 4.3 $BOKS_var/ssoconfig file to new format.
# This is actually be run on a post 4.3 ssoconfig file as well,
# but will leave it unmodified.
#
conv_ssoconfig () {
    if [ -f $BOKS_var/ssoconfig ]; then
	tmpfile=/tmp/ssoconfig.$$
	nawk -F: '
/^#/  {print; next}
/^[^:]*:[^:{]*{/ {print; next};
 {if (NF == 5 && $2 == "oracle") {printf "service=\"%s\"; type=\"%s\"; servicehost=\"%s\"; serviceport=\"%s\"; oraclehome=\"%s\"\n", $1, $2, $3, $4, $5}
   else if (NF == 7 && $2 == "sybase") {printf "service=\"%s\"; type=\"%s\"; servicehost=\"%s\"; serviceport=\"%s\"; servicename=\"%s\"; sybasehost=\"%s\"; sybaseport=\"%s\"\n", $1, $2, $3, $4, $5, $6, $7}
   else {print}}' < $BOKS_var/ssoconfig > $tmpfile 2>/dev/null

	# Try to avoid destroying old file on errors
	if [ $? -eq 0 ]; then
	    cp -f $tmpfile $BOKS_var/ssoconfig > /dev/null 2>&1
	fi
	rm -f $tmpfile > /dev/null 2>&1
    fi
}

# upgrade $BOKS_etc/ENV.kpkg
#
# Add new variables to the ENV.kpkg file with reasonable default
# if they are missing.
#
upgrade_envkpkg () {
    file="$BOKS_etc/ENV.kpkg"
    if [ -f "$file" ]; then
	# 4.3 -> 4.4, compat added. Assume it should have
	# value 1 after upgrade
	if grep '^compat=' "$file" > /dev/null 2>&1; then
	    # already there, no need to do anything
	    :
	else
	    # add it at the end
	    echo "compat=1" >> "$file"
	fi
	# 4.3 -> 4.4 default country is changed from XX country
	# to just XX (where XX are two upper case chars
	# and country may contain spaces)
	tmpfile1=/tmp/kpkg1.$$
	tmpfile2=/tmp/kpkg2.$$
	if grep '^default_country=[A-Z][A-Z] .*' "$file" > $tmpfile1 2>/dev/null; then
	   # ok, need to modify
	   # first get all but default country line
	   grep -v '^default_country=[A-Z][A-Z] .*' "$file" > $tmpfile2 2>/dev/null
	   # now modify default country line and append
	   sed 's/^default_country=\([A-Z][A-Z]\) .*/default_country=\1/' $tmpfile1 >> $tmpfile2
	   cp $tmpfile2 "$file" > /dev/null 2>&1
	   rm -f $tmpfile2 > /dev/null 2>&1
	fi
	rm -f $tmpfile1 > /dev/null 2>&1
    fi
}


PACKBASEOPTS="-b -i"
VERIFY=
USAGE="usage: boks_bru -r -d device\n\t-b -d device\n\t-m -d device\n\t-e -d device\n\t-s -d device\n\t-p [-l] -d device\n\t-u -d device"


set -- `getopt brmespuld: $*`
if [ $? != 0 ]
then
	echo "$USAGE" >&2
	exit 1
fi
for i in $*
do
	case $i in
	-b)		BACKUP=true; shift;;
	-r)		RESTORE=true; shift;;
	-s)		SHOW=true; shift;;
	-m)		MOVELOGS=true; shift;;
	-e)		RESTLOGS=true; shift;;
	-p)		RUN_PACKBASE=true; shift;;
	-u)		UNPACKBASE=true; shift;;
	-l)		PACKBASEOPTS="$PACKBASEOPTS -L"; shift;;
	-d)		DEVICE=$2; shift; shift;;
	-V)		VERIFY="$2"; shift;;
	--)		shift; break;;
	esac
done

setboksenv MLANG
setboksenv NLSINFO
setboksenv MENUASCII

MLANG=${MLANG:-eng}
NLSINFO=${NLSINFO:-$BOKS_lib/nls}
MENUASCII=${MENUASCII:-7BIT}

export PATH MLANG NLSINFO MENUSASCII

# Read messages
eval "`msglist $BOKS_lib/mess boks_bru 2>/dev/null`"


# Make sure that DEVICE is set and
# make it relative to current directory,
# if given with relative path 
#
if [ -z "$DEVICE" ]; then
	echo "$USAGE" >&2
	exit 1
fi
if expr "$DEVICE" : '[^/]' >/dev/null; then
	DEVICE=`pwd`/$DEVICE
fi


#
# Perform some actual work...
#
TMPD=$BOKS_tmp/boks_bru$$.d
if [ "$BACKUP" = true ]; then
	# Backup of BoKS programs and database
	#
	mkdir $TMPD || exit 1
	ln -s $BOKS_etc $TMPD/etc
	ln -s $BOKS_data $TMPD/data
	$BOKS_sbin/Boot -k
	(cd $TMPD && tar cvf $DEVICE etc/* data/*)
	$BOKS_sbin/Boot
	rm -rf $TMPD
elif [ "$RESTORE" = true ]; then
	#
	# Restore of BoKS programs and database
	#
	if [ ! -f "$DEVICE" ]; then
	    printf "${MESS_no_file:-%s: no such file or directory}\n" \
		"$DEVICE" 
	    exit 1
	fi
	if [ -n "$VERIFY" ]; then
	    x=`tar tf $DEVICE $VERIFY 2>/dev/null`
	    if [ -z "$x" ]; then
		exit 1
	    fi
	fi
	mkdir $TMPD || exit 1
	ln -s $BOKS_etc $TMPD/etc
	ln -s $BOKS_data $TMPD/data
	$BOKS_sbin/Boot -k
	(cd $TMPD && tar xvf "$DEVICE")
	$BOKS_sbin/Boot
	rm -rf $TMPD
elif [ "$MOVELOGS" = true ]; then
        #
	# Move logs to backup media
	#
	getlogdir
	cd "$LOGDIR" || \
		{ printf "${MESS_no_logdir:-Log directory %s not found}\n" $LOGDIR >&2; exit 1; }
	files="`ls L[0-9][0-9][0-9][0-9][0-9][0-9]?[0-9][0-9][0-9][0-9][0-9][0-9] 2> /dev/null`"
	if [ -n "$files" ]; then
		tar cvf $DEVICE $files
		bkslog -L log_backup -a "Logs backuped to $DEVICE and removed"
		bkslog -s -L log_backup -a "Logs backuped to $DEVICE and removed"
		rm -f $files
	else
		printf "${MESS_no_logfiles:-No log files found in %s}\n" $LOGDIR
	fi

elif [ "$RESTLOGS" = true ]; then
	#
	# Restore logs from backup media
	#
	getlogdir
	cd "$LOGDIR" || \
		(printf "${MESS_no_logdir:-Log directory %s not found}\n" $LOGDIR >&2; exit 1)
	tar xvf $DEVICE

elif [ "$SHOW" = true ]; then
	#
	# Show contents of backup media
	#
	tar tvf $DEVICE
elif [ "$RUN_PACKBASE" = true ]; then
	#
	# Save the database and (possibly) loggfiles in "shar-format"
	# (as done by Uninstall).
	#
	# Save the BoKS database on $DEVICE, which may be a character 
	# special (tape-) device (see the "dd_device" funktion above).
	# The database is read using "packbase" and will thus be in the same
	# format as the file /usr/tmp/BOKS-DB created by "Uninstall".
	#
	# See packbase(1B) for a description of options to packbase.

	# list of files in BOKS_etc to be saved. 
	SAVE=
	SAVEF=$BOKS_etc/savefiles
	list="`test -f $SAVEF && grep -v '^#' $SAVEF`"
	for f in `cd $BOKS_etc; echo $list`; do
	    test -s "$BOKS_etc/$f" && SAVE="$SAVE $f"
	done

	p=`pwd`
	cd $BOKS_var
	SAVEF=$BOKS_var/savefiles
	list="`test -f $SAVEF && grep -v '^#' $SAVEF`"
	VARSAVE=`ls -1d $list 2>/dev/null | sed -e 's/.*/"&"/'`
	cd "$p"

	setboksenv ENVDONTSAVELIST

	# If DEVICE is character special, we will pad the outputfile with 
	# "newline" characters to make it fit on an even 512 byte boundary 
	# Writing will then be done using "dd" with a blocksize of 10k byte.
	#
	# The padding is currently done by the awful awk-script below, which
	# will only work as long as the output contains just plain text!
	(cd $BOKS_etc \
	    && eval packbase $PACKBASEOPTS -E "\"$ENVDONTSAVELIST\"" -- \
	    -C '\$BOKS_etc' $SAVE -c $BOKS_var -C '\$BOKS_var' $VARSAVE) \
	    | dd_device Write $DEVICE
elif [ "$UNPACKBASE" = true ]; then
	#
	# Unpack shar created by "packbase" (a' la Install)
	#
	failed=false
	getlogdir
	logadm -n -f		# Start new log

	$BOKS_sbin/Boot -k
	boksdiag -f createshm
	mkdir $BOKS_data/save
	mv -f $BOKS_data/*.dat $BOKS_data/save/
	rm -f "$LOGDIR/LOG.bak"
	test -f "$LOGDIR/LOG" && mv "$LOGDIR/LOG" "$LOGDIR/LOG.bak"
	ETC_SAVEFILE=$BOKS_tmp/etc_savefiles.$$
	VAR_SAVEFILE=$BOKS_tmp/var_savefiles.$$
	cp -f $BOKS_etc/savefiles $ETC_SAVEFILE
	cp -f $BOKS_var/savefiles $VAR_SAVEFILE

	# Unpack...
	#
	if (cd $BOKS_etc && dd_device Read "$DEVICE" | /bin/sh) &&
	    test -z "`boksdiag db missing`"
	then
	    failed=false
	    cat $BOKS_etc/savefiles >> $ETC_SAVEFILE
	    sort -u $ETC_SAVEFILE > $BOKS_etc/savefiles
	    cat $BOKS_var/savefiles >> $VAR_SAVEFILE
	    sort -u $VAR_SAVEFILE > $BOKS_var/savefiles
	else
	    echo "${MESS_unable_to_restore_db:-Restore database failed}"
	    # Restore original database
	    rm -f $BOKS_data/*.dat
	    mv $BOKS_data/save/*.dat $BOKS_data
	    cp $ETC_SAVEFILE $BOKS_etc/savefiles
	    cp $VAR_SAVEFILE $BOKS_var/savefiles
	    failed=true
	fi
	$BOKS_sbin/Boot -k	# Clean up IPC...
	rm -f $VAR_SAVEFILE $ETC_SAVEFILE
	rm -fr $BOKS_data/save
	mv "$LOGDIR/LOG.bak" "$LOGDIR/LOG" 2>/dev/null

	$BOKS_sbin/Boot
	$failed && exit 1
	certs2db
	conv_ssoconfig
	upgrade_envkpkg
else
	echo "$USAGE" >&2
	exit 1
fi
exit 0
