#! /bin/sh
#
# lpsupdate -- Script to update an existing version of the
#              Digital PrintServer (LPS) Software
#
# # @(#)lpsupdate	1.6	LPS_UNX_COM	04/18/95
#
# RCS $Id: lpsupdate 1.2 1997/10/28 17:02:16 jds Exp $
#
# Note:  This script can only perform an update to LPS V5.1 or V5.2 from
#        an installation of a prior release of the LPS software.
#
# This script MUST ONLY be executed by the "lpsinstall" script.
###

SCRIPTPATH=$0
SCRIPTNAME=`basename $0`

# Shell variables with fixed definitions

ABORT="kill -1 $$"
PRODUCT="PrintServer Software"
VERSION="5.2"
PRESERVE=false	# Controls whether savefile is used in subscripts
SILENT=true	# Keeps subscripts as quiet as possible

export PRESERVE SILENT

# Shell script exit values

EX_NOTNECESSARY=0	# Update not necessary
EX_SUCCESS=1		# Update performed successfully
EX_FAILURE=2		# Update attempted, but failed
EX_INTERNALERROR=3	# Update failed due to internal error

# Shell variables that may already be defined upon entry

: ${CONFIRM:=false}
: ${LPSODB:=/etc/lpsodb}
: ${LPSODBLIST:=/etc/lpsodblist}
: ${PAGER:=more}
: ${TMPDIR:=/tmp}

# Shell variables that will change later on

OLDLPSODB=""

#----------------------------------------------------------------------

# Debug()
#
# Function to provide typical "debug" output based on the value of
# the LPSDEBUG variable.

Debug ()
{
    if [ "$LPSDEBUG" ]
    then
	echo "DEBUG: $*"
    fi

    return 0
}

#----------------------------------------------------------------------

# Verify that we have been invoked by the "lpsinstall" master shell script.

Debug "Executing the $SCRIPTNAME script..."

if [ "$LPSINSTALL" ]
then
    if [ `$PSPID $LPSINSTALL | wc -l` -eq 2 ]
    then
	:
    else
	LPSINSTALL=""
    fi
fi

if [ -z "$LPSINSTALL" ]
then
    echo
    echo '    This script can only be executed by the "lpsinstall" script!'
    exit $EX_INTERNALERROR
fi

#----------------------------------------------------------------------

# Function to restore the old LPSODB to its former self

RestoreLPSODB ()
{
    if [ "$OLDLPSODB" ]
    then
	echo "Restoring the original LPS Object Database file..."

	if [ -f $LPSODB ]
	then
	    mv $LPSODB ${LPSODB}.MID-UPDATE
	fi

	if mv $OLDLPSODB $LPSODB
	then
	    rc=0
	else
	    rc=1
	    echo
	    echo "    Failure to restore the database from file $OLDLPSODB !!!"
	    echo
	    pause
	fi
    else
	rc=0
    fi

    return $rc
}

#----------------------------------------------------------------------

# Function to be executed upon encountering a termination signal

Trap ()
{
    echo
    echo $SCRIPTNAME script terminating...
    echo

    RestoreLPSODB

    echo
    echo $PRODUCT was NOT completely updated.
    echo

    if [ "$ENV_LPSTMP" ] ; then rm -f $ENV_LPSTMP/*.$$ ; fi
    rm -f $TMPDIR/*.$$
    rm -f ./*.$$

    exit $EX_FAILURE
}

#----------------------------------------------------------------------

# Setup activities to be executed upon encountering certain signals

trap Trap 1 2 3 15

#----------------------------------------------------------------------

# ManualRemove ()
#
# Common announcement function for when the user must manually remove
# the current installation.

ManualRemove ()
{
    cat << EOF

    Sorry, but it appears that the current installation is broken in
    some way such that it can not be automatically updated.  As a result,
    you will have to remove the current installation by following the
    instructions in the Management Guide provided with the the $VERSION
    of this new software.

EOF
    pause
}

#----------------------------------------------------------------------

# mknewobjvars()

# Shell function to create "NEW" variables associated with a particular
# object type (class).  Stolen direct from the mkoldobjvars() function
# from the lpssfuncs file.
#
# Parameters:
#    $1 - The object type (class) identifier (eg, "ENV", "PC")
#
# Return value is always 0, implying success.

mknewobjvars ()
{
    cprefix=$1

    for var in `set | sed -n -e "s/^\(${cprefix}_.*\)=.*/\1/p"`
    do
	eval NEW$var="\$$var"
    done

    return 0
}

#----------------------------------------------------------------------

#		      >>>>> DISCOVERY Phase <<<<<
#
# Import the ENV object attributes, then get the list of all currently
# defined MC/PC objects.

Debug "Checking for existence of $LPSODB ..."

# If no $LPSODB file exists, then there's no update to do

if [ ! -f $LPSODB ]
then
    exit $EX_NOTNECESSARY
fi

# Extract the ENV "sysversion" attribute from the $LPSODB to see what
# version we're dealing with.

Debug "Acquiring the current software version from $LPSODB ..."

error=false

if OLDLPSVERSION=`$BINDIR/lpsodblist -f $LPSODB -e -v sysversion`
then
    # See if the currently installed software needs updating,
    # and if so, then set OLDLPSVERSION accordingly, and set
    # LPSODBLIST to the proper version that can read this LPSODB.

    case "$OLDLPSVERSION" in
	"V4.0" ) OLDLPSVERSION="40"
		 LPSODBLIST=lpsodblist40
		 ;;
	 "4.1" ) OLDLPSVERSION="41"
		 LPSODBLIST=lpsodblist41
		 ;;
	 "4.2" ) OLDLPSVERSION="42"
		 LPSODBLIST=lpsodblist42
		 ;;
	 "5.0" ) OLDLPSVERSION="50"
		 LPSODBLIST=lpsodblist50
		 ;;
	 "5.1" ) # A rigorous update is not necessary if the user is
		 # is simply re-installing the software; this situation
		 # is already handled by the "lpsinitodb" script, so we
		 # just immmediately exit here, saying that "no update
		 # is required" and let lpsinitodb handle everything.

		 exit $EX_NOTNECESSARY
		 ;;
	 "5.2" ) # There are no odb changes in V5.2, and sysversion remains at
	         # 5.1 for this release.

		 exit $EX_NOTNECESSARY
		 ;;
	     * ) echo "    Unknown LPS version found: $OLDLPSVERSION"
		 error=true
		 ;;
    esac
fi

if $error
then
    :	# This is handled in just a little bit
else


    echo
    echo "Updating the software on $LOCALHOST ..."
    echo

    pause

    . $FUNCS	    # Import the common LPS shell functions

    echo
    echo "Acquiring the list of all defined LPS objects..."

    GETODB="$BINDIR/$LPSODBLIST -f $LPSODB"

    if OLDPSLIST=`$GETODB -c ps`
    then
	if OLDMCLIST=`$GETODB -c mc`
	then
	    if OLDPCLIST=`$GETODB -c pc`
	    then
		error=false
	    else
		echo "    Failure to extract all Print Client definitions!"
	    fi
	else
	    echo "    Failure to extract all Management Client definitions!"
	fi
    else
	echo "    Failure to extract all PrintServer printer definitions!"
    fi
fi

# If at this point we have encountered an error, then there's nothing we
# can do to effectively and *accurately* update the current installation.
# If this happens, then we offer our condolences and punt.

if $error
then
    ManualRemove
    $ABORT
fi

#----------------------------------------------------------------------

#		      >>>>> SHUTDOWN Phase <<<<<

echo
pause "Press RETURN to begin shutting down all clients ..."

echo
echo "Shutting down all LPS Management and Print Clients on $LOCALHOST ..."

# Shutdown all defined Print Client (PC) objects
#
# If this is a SV3 printing model that requires the LP spooling system
# to be shutdown before you can down a print queue, then do so now.

echo

RESTARTLP=false		# So that we know later to restart LP

TMPFILE=$TMPDIR/LPctrl.$$

if [ "$PCTYPE" = SV3 ]
then
    if [ -f scripts/stopLP.SV3 -o -f scripts/startLP.SV3 ]
    then
	if [ -f scripts/stopLP.SV3 ]
	then
	    if scripts/stopLP.SV3
	    then
		RESTARTLP=true
	    else
		$ABORT
	    fi
	else			    # No script?  Do it manually, then.
	    if lpstat -r | grep "is not running" > /dev/null 2>&1
	    then
		echo "The LP spooling system is already shutdown."
	    else
		echo "Shutting down the LP spooling system..."

		if lpshut > $TMPFILE 2>&1
		then
		    RESTARTLP=true
		else
		    cat $TMPFILE

		    cat << END_OF_INPUT
    Sorry, but it appears that the LP spooling system did not stop
    as directed.  Please try to fix this problem and try again.
END_OF_INPUT
		    rm -f $TMPFILE
		    $ABORT
		fi
	    fi
	fi
    fi
fi

# Shutdown all PC queues

for obj in $OLDPCLIST
do
    echo "--- Shutting down Print Client $obj ... "

    if getobject true PC $obj
    then
	expobjvars PC

	reason="Temporarily unavailable due to software update"

	if downq.$PCTYPE $obj false "$reason"
	then
	    :
	else
	    echo
	    echo "Unable to shutdown the print queue!"

	    if yesno y "Do you wish to continue anyway"
	    then
		:
	    else
		$ABORT
	    fi
	fi
    else
	ManualRemove
	$ABORT
    fi
done

# Restart the LP system IFF we were the ones who stopped it

if $RESTARTLP
then
    echo "Restarting the LP spooling system..."

    if lpsched > $TMPFILE 2>&1
    then
	:
    else
	cat $TMPFILE

	cat << END_OF_INPUT

    Sorry, but it appears that the LP spooling system did not
    restart as directed.  Please look into this problem and
    try to get it restarted (using the "lpsched" command) after
    this script completes.
END_OF_INPUT
	pause
    fi
fi

rm -f $TMPFILE

# Shutdown all defined MC objects

echo

for obj in $OLDMCLIST
do
    echo "--- Shutting down Management Client $obj ... "

    if getobject true MC $obj
    then
	if stopMC $obj
	then
	    :
	else
	    if yesno y "Do you wish to continue anyway"
	    then
		:
	    else
		$ABORT
	    fi
	fi
    else
	$ABORT
    fi
done

#----------------------------------------------------------------------

#		      >>>>> UPDATE Phase <<<<<

echo
pause "Press RETURN to begin updating all LPS object definitions..."

# First we need rename the current (ie, "old") LPSODB, since we will be
# creating an entirely "new" version.  Then, some new variables must be
# defined that allow us to simultaneously reference both the old AND the
# new LPSODB, since the update mechanism is such that we read an existing
# definition from the old LPSODB, then create a new, updated definition
# in the new LPSODB.

OLDLPSODB=${LPSODB}.V$OLDLPSVERSION
OLDLPSODBLIST=$LPSODBLIST
NEWLPSODB=$LPSODB
NEWLPSODBLIST=$BINDIR/lpsodblist

if mv $LPSODB $OLDLPSODB
then
    :
else
    echo
    echo "    Unable to rename the current database to $OLDLPSODB !!!"
    $ABORT
fi

# Create a null LPSODB to ensure we can write into that directory, etc.

if touch $NEWLPSODB && chmod 655 $NEWLPSODB
then
    :
else
    echo
    echo "    Unable to create the new LPS Object Database $NEWLPSODB !!!"
    $ABORT
fi

# Note that in order to use existing supporting scripts and functions we
# need to play some games regarding the dynamic redefinition of both the
# LPSODB and LPSODBLIST variables, switching repeatedly between the old
# and new versions.  Hence, the following function serves as clean wrapper
# around the venerable (and centralized) "getobject()" function.

getold ()
{
    inherit=$1
    class=$2
    name=$3

    LPSODB_xxx=$LPSODB
    LPSODBLIST_xxx=$LPSODBLIST

    LPSODB=$OLDLPSODB
    LPSODBLIST=$OLDLPSODBLIST

    getobject $inherit $class $name

    rc=$?        # Save getobject()'s return value 

    LPSODB=$LPSODB_xxx
    LPSODBLIST=$LPSODBLIST_xxx

    return $rc   # Use getobject()'s return value
}

# Read in the old ENV definition, make all necessary changes, then
# create a new ENV definition within the new LPSODB.
#
# In order to do this, we must play a few games to ensure that all
# the right values get set to the right variables.  First, the old
# (ie, existing) ENV object variables are read in from the existing
# LPSODB, then "OLD" variables (ie, "OLDENV_xxx") are created from
# those variables; then, the new variables are read in from the new
# software kit's "lpsodb.GENERIC" file so as to establish the proper
# default values for this new version of the software.  Note, however,
# that an extra special step must be performed, whereby the platform-
# specific variables must be manually applied to the corresponding
# new ENV variables in order to establish the proper values for these
# platform-specific variables.  Also note that in order for all of this
# to work correctly, the old ENV variables must be read in TWICE, once
# to create the "OLDENV_xxx" variables, and once to overwrite the new,
# generic values so as to preserve the original (valid) definitions.

echo "  Updating the Environment object..."

error=true

OFILE=$TMPDIR/lpsupd.$$

rm -f $OFILE

if getold false ENV      # Get old ENV definitions
then
    mkoldobjvars ENV            # Create "OLDENV_xxx" vars from "ENV_xxx" vars

    LPSODB=./lpsodb.GENERIC     # Setup to use the GENERIC version for ENV
    LPSODBLIST=$BINDIR/lpsodblist

    # The hairy lpsodblist command immediately below creates the list
    # of ENV_xxx vars in $OFILE without performing path resolution.

    if $BINDIR/lpsodblist -e -R -B -f lpsodb.GENERIC > $OFILE
    then
	. $OFILE	# Import the new ENV vars

	# Perform the manual application of platform-specific values
	# (Note: this little section really should be contained within
	#        it's own separate, centralized, re-usable script!)

	ENV_ACCTUNIT="$ACCTUNIT"
	ENV_LPSACCT="$LPSACCT"
	ENV_LPSLOG="$LPSLOG"
	ENV_MAILPROG="$MAILPROG"
	ENV_MAILOPTS="$MAILOPTS"
	ENV_TOPQDIR="$TOPQDIR"

	LPSODB=$LPSODB_xxx           # Reset to previous values
	LPSODBLIST=$LPSODBLIST_xxx
	
	# Create "NEW" versions of the GENERIC ENV variables

	mknewobjvars ENV

	# Update the ENV object, then create the new LPSODB file

	if getold false ENV          # Reset ENV vars to OLD values
	then
	    if . scripts/upd.ENV     # Update all ENV_xxx vars
	    then
	    	expobjvars ENV       # Export all "ENV_xxx" vars

		if mklpsodb $NEWLPSODB $OFILE ""  # Create the new LPSODB
		then
		    error=false    # Success IFF we get here!
		fi
	    else
		echo "    Failure to re-extract the old ENV definition !!!"
	    fi
	else
	    echo "    Failure to update the ENV definition !!!"
	fi
    else
	echo "    Failure to extract ENV definition from $LPSODB !!!"
    fi
else
    echo
    echo "    Unable to extract old ENV definition!"
fi

if $error
then
    ManualRemove
    $ABORT
fi

TMPODB=$TMPDIR/lpsodb.$$	# For use by updateLPSODB

# Update all printer and client objects

for updclass in PS PC MC
do
    eval updlist="\$OLD${updclass}LIST"
    upddesc=`getobjdesc $updclass`

    for obj in $updlist
    do
	echo "  Updating $upddesc $obj ..."

	if getold true $updclass $obj
	then
	    if . scripts/upd.$updclass
	    then
		expobjvars $updclass

		if mkodbdef $updclass Alist.$updclass $OFILE
		then
		    if updateLPSODB $NEWLPSODB add $updclass $obj "" $OFILE $TMPODB
		    then
			:	# Success!
		    else
			$ABORT
		    fi
		else
		    echo "    Failure to create new $upddesc definition!!!"
		    $ABORT
		fi
	    else
		echo "    Failure to update $upddesc $obj !!!"
		$ABORT
	    fi
	else
	    echo "    Failure to extract old $upddesc definition !!!"
	    $ABORT
	fi
    done
done

#----------------------------------------------------------------------

#		    >>>>> NOTIFICATION Phase <<<<<

echo
pause "Press RETURN to complete this portion of the update procedure..."

cat > $ODBMSG << EOF
This version of the software was installed over the previous installation.
Please follow the instructions in the Installation and Management Guide to
effect the complete update of the software, including the rebooting of all
PrintServer printers.
EOF

exit $EX_SUCCESS

#
# Local Variables:
# fill-column:78
# page-delimiter:"^#---"
# End:
