#! /bin/sh
#
# lpsinstall -- Install a PrintServer Software Kit
#
# @(#)lpsinstall	1.57	LPS_UNX_COM	6/7/95
#
# Copyright 1995   Digital Equipment Corporation, Maynard, MA
#
# DESCRIPTION:
#
# Installation script for initializing the LPS Object Database and installing
# all production components of the product on the local system.  In the case
# of the BSD UNIX Source Kit, all binaries are also created from the source
# modules provided.
#
# This script should only be run ONCE after the product has been transferred
# from the distribution media into a disk directory (usually referred to as
# the "LPSKIT" directory).
#
# A bit of extra debugging is available if the LPSDEBUG variable exists
# and is non-null (can be any value).
# -----------------------------------------------------------------------------

# Initialize most fixed-value variables

SCRIPTNAME="`basename $0`"

: ${ABORT="kill -1 $$"}
: ${BINROOT="./.binroot"}
: ${HELP="true"}
: ${KITLIST="KITLIST"}
: ${LPSINSTALL="$$"}
: ${LPSODBGENERIC:="./lpsodb.GENERIC"}
: ${PAGER:=more}
: ${TMPDIR="/tmp"}
#
# The official LPS version for this installation script
#
VERSION="5.1"	# Hardcoded for every release

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

# Initialize other critical global variables that will possibly change
# during execution of this script, but are otherwise needed immediately.

: ${ECHON="/bin/echo -n"}
ENV_LPSTMP="/tmp"
PRODUCT="PrintServer Software Kit"

# Export global variables used exclusively by this script
# and its subscripts.

export BINDIR BINROOT
export INSTFLAG
export LPSODBGENERIC LPSINSTALL

SHELL=/bin/sh				# So SCO doesn't mess up
export SHELL

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

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

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

    return 0
}

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

# To make it easier to centralize the eight bazillion temporary files
# created by the subscripts, attempt to create a directory within the
# currently defined TMPDIR, save the current definition in OLDTMPDIR,
# then create a subdirectory and redefine TMPDIR to point to that new
# directory.  When we quit, we will delete the entire subdirectory in
# one fell swoop...and keep the system manager happy.

OLDTMPDIR=$TMPDIR
NEWTMPDIR=$TMPDIR/lpsinstall.$$

if [ ! -f $NEWTMPDIR -a ! -d $NEWTMPDIR ]
then
    if mkdir $NEWTMPDIR > /dev/null 2>&1
    then
	TMPDIR=$NEWTMPDIR
	NEWTMPDIR=""		# Must be blank for subdirectory removal!
    fi
fi

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

# Define a "cleanup" function to perform cleanup activities before exiting.
# The only parameter is an integer exit code.  This function should be
# called whenever this script needs to exit after this point.

cleanup ()
{
    if [ -z "$NEWTMPDIR" ]   # ONLY if we created a complete tmp directory!
    then
	rm -rf $TMPDIR
    fi

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

    return 0
}

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

# Setup activities to be executed upon encountering certain signals

trap 'echo ; \
      echo $SCRIPTNAME script terminating... ; \
      echo ; \
      echo $PRODUCT was NOT completely installed. ; \
      echo ; \
      cleanup ; \
      echo ; \
      exit 1' \
      1 2 3 15

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

# This is the actual top of the script as "seen" by the user.
#
# Here we display the title of this script, then perform certain
# environmental checks to ensure the user is sufficiently privileged
# and that the current working directory is the top of the kit
# directory tree as loaded from the distribution media.
#
# Here is also where the overall platform environment is determined,
# and all associated global variables relating to platform-specific
# issues are set.

cat << ENDOFINPUT

PrintServer Software Installation  (lpsinstall)

Just a moment while the local environment is examined...

ENDOFINPUT

# Verify the user is currently executing as the superuser.
# This is not a very complete test, but it should be sufficient.

error=false

testfile=/tstroot.$$
if touch $testfile > /dev/null 2>&1
then
    :
else
    error=true
fi

rm -f $testfile

# Ensure we are running in the kit directory

if [ ! -x lpsinstall ]
then
    error=true
fi

if $error
then
    cat << END_OF_INPUT

    To run this script you must be running as the super-user (root),
    and your current working directory must be set to the directory
    used to load the kit from the distribution media.

END_OF_INPUT
    exit 1
fi

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

# Import the common LPS shell functions

if . scripts/lpsshfuncs
then
    :
else
    $PAGER << END_OF_INPUT

    Sorry, but the $FUNCS shell
    script file could not be imported.  This may
    imply that the kit does not exist in its
    entirety, which means you will have to reload
    the software from the distribution media.

END_OF_INPUT
    exit 1
fi

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

# Determine whether the software is on read-only (ie, CDROM) media
# or not, then set the corresponding variable.

if touch ./fstest > /dev/null 2>&1
then
    rm -f ./fstest
    WRITABLE_KIT=true
else
    WRITABLE_KIT=false
fi

export WRITABLE_KIT

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

# Perform the critical determination of the local platform type and
# set all related global variables dealing with platform-specific things.
#
# Note that as an extra special precaution against possible
# mishandling of the loading of the kit from the distribution media,
# all script files are explicitly set for execute access IFF the
# current working directory is writable and the LPSDEBUG variable
# resolves to a non-null value.

if . scripts/setkitvars
then
    if $WRITABLE_KIT
    then
	if [ "$LPSDEBUG" ]
	then
	    chmod a+x ./scripts/*
	fi
    fi
else
    cat << ENDOFINPUT

	All platform-specific settings could not be performed!

	This probably implies that the kit will have to be reloaded
	onto your system from the distribution media.

ENDOFINPUT

    exit 1
fi

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

# Display the local environment and pertinent kit information.

cat << ENDOFINPUT
Installation of the $PRODUCT

    Environment:
        Operating system name:    $OSNAME
        Operating system version: $OSVER
        Operating system type:    $OSTYPE
        Hardware platform type:   $PLATFORM
        Printing system model:    $PCTYPE

ENDOFINPUT

pause

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

# Further platform "discovery" is done based on whether this is a
# Source Kit or a Binary Kit.

error=""   # Overall error-catcher & message content

CWD="`pwd`"

MULTIBINSETS=false
export MULTIBINSETS

if $SRCKIT	# If this is a Source Kit
then

    # Construct the target binary executables directory based
    # on the operating system name and version.
    #
    # Note that for Solaris systems, due to the support for multiple
    # hardware architectures, the PLATFORM string is appended to the
    # construction of the BINDIR path.

    BINDIR="$CWD/bin/${OSNAME}_${OSVER}"

    if [ "$OSNAME" = "Solaris" ]
    then
	BINDIR="${BINDIR}_${PLATFORM}"
    fi

else   # We are dealing with a Binary Kit

    # Determine the binary directory to be used for the installation.
    #
    # See if this kit provides more than one set of executables.
    # If more than one set of binaries exist, then display the list
    # to the user and let the user select; otherwise, if only one set
    # of executables exist, then use that set.

    binlist=`find bin -type d -print`
    bincnt=`echo $binlist | wc -w | $TR -d " "`

    case $bincnt in
	1 ) BINDIR=$CWD/bin
	    ;;

	2 ) BINDIR=$CWD/`echo $binlist | cut -d' ' -f2`
	    ;;

	* ) MULTIBINSETS=true

	    bindirs=""
	    
	    for d in $binlist
	    do
	        if [ $d != bin ]
		then
		    bindirs="$bindirs `basename $d`"
		fi
	    done

	    # Determine what we think should be the proper binary set to use,
	    # based on the local platform variables.
	    #
	    # Note that for Solaris systems, due to the support for multiple
	    # hardware architectures, the PLATFORM string is appended to the
	    # construction of the BINDIR path.

	    BINDIR="${OSNAME}_${OSVER}"

	    if [ "$OSNAME" = "Solaris" ]
	    then
		BINDIR="${BINDIR}_${PLATFORM}"
	    fi

	    cat << EOF

Multiple versions of the $PRODUCT
are available with this software kit.  Please choose one of the following
versions based on your local system configuration.  If your operating
system version does not match one of those listed below, then please
choose the version that is most recent to the operating system version
currently running on your system.

You are currently running $OSNAME version $OSVER on ${LOCALHOST}.
EOF

	    question="Which version do you want to install"

	    choose "$BINDIR" "$question" $bindirs

	    BINDIR=$CWD/bin/$RESPONSE
	    ;;
    esac
fi

cd $CWD

# Reset the PATH variable to specify that the kit script subdirectory
# and the resolved BINDIR directory precede all other PATH components.

PATH="${BINDIR}:$PATH"

unset CWD	# Should no longer be needed

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

# Check to ensure that all kit components are present

echo
echo "Checking to ensure all kit components are present..."

if kitcheck
then
    :
else
    if [ "$LPSDEBUG" ]
    then
	if yesno n "Continue with the installation anyway"
	then
	    :
	else
	    exit 1
	fi
    else
	cat << END_OF_INPUT

    Something is wrong with the distribution kit as it currently exists
    on your system in `pwd`.  Please reload
    the software from the distribution media and rerun this script.

END_OF_INPUT
	exit 1
    fi
fi

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

# If this is a Source Kit, then ensure all software components are
# properly built and all resulting binaries transfered to the proper
# binary executables directory.

if $SRCKIT
then
    echo "Checking to see if all software components have been built..."
    echo

    if buildkit $KITCLASS ./src $BINDIR
    then
	:
    else
	$ABORT
    fi
fi

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

# Announce the purpose of this script and ask for confirmation

showhelp true "

This script initializes the LPS Object Database and installs all
components of the $PRODUCT kit
on your system.

You will be given the opportunity to either select the default GENERIC
installation, or specify custom values for each installation
configuration variable.

Selecting the GENERIC installation is the fastest way to get the kit
up and running.  This installation assumes that you want to leave all
kit components in the directories where they were copied from the
distribution media.  Other runtime configuration variables will be set
to values that are typical for a wide range of system configurations
and policies.

Selecting a custom installation allows you to decide where various kit
directories should reside, and set one or more of the many
configuration variables.

Before you are asked to select an installation type, you will be shown
the values of all configuration variables for the GENERIC
installation.  After examining the values, decide whether the current
values are acceptable, or whether you need to change one or more of
the variable values.

NOTE:  If a previous version of the software already exists on your
       system, then the software will be automatically updated with
       this newer version.

You may abort the installation procedure at any time by pressing
your terminal's \"interrupt\" key (usually the CTRL/C key).
"

if yesno y "Do you want to continue with the installation"
then
    :
else
    echo
    exit 1
fi

ODBMSG="/tmp/odbmsg.$$"	     # Used for the final notification email msg
cat /dev/null > $ODBMSG	     # Create an empty file
export ODBMSG		     # Needed by lpsinitodb and lpsupdate

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

# The user wants to continue the installation, so now we run thru the
# entire kit directory tree and set the owner/group of all directories
# and files.
#
#  [-- Currently done only with LPSDEBUG due to performance costs,
#      and it's not clear whether this is really necessary or not. --]

if [ "$LPSDEBUG" ] && $WRITABLE_KIT
then
    echo
    echo "Setting ownership rights for all kit components..."

###    find .         -exec chown root   {} \; -exec chgrp bin {} \;
###    find ./servers -exec chown daemon {} \;
fi

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

# Check to see if an update should be performed and proceed accordingly.

NOTUPDATED=true  # Critical flag variable to control subsequent actions

lpsupdate

case $? in
    0 ) Debug "No update required"
        ;;
    1 ) Debug "Update has been performed successfully"
	NOTUPDATED=false
        ;;
    2 ) Debug "Update has failed, removal of existing software is necessary"
	exit 1
        ;;
    * ) echo
	echo "An internal problem has been encountered during the installation"
	echo "procedure, probably due to problems in loading this version of"
	echo "the software on your system."
	echo
	echo "Please re-install the $VERSION version of the software"
	echo "and try again."
	exit 1
        ;;
esac

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

# Invoke the subscript used to inquire about the type of installation
# to be performed (GENERIC vs. custom) and initialize the LPS Object
# Database (LPSODB).
#
# NOTE:  This is done IFF no software update has just been done!
#
# If this script exits with a value of zero (0), then it is assumed
# the LPSODB initialization was successful and that a fully defined,
# initial LPSODB is ready for use.  In this case, the attributes of
# the LPS Environment object are extracted and imported to be used
# in directing the subsequent installation activities.
#
# If, on the other hand, this script exits with any value other than
# zero, it is assumed the installation procedure should be terminated.

if $NOTUPDATED
then
    echo
    pause "Press RETURN to begin configuring the LPS Object Database... "

    if lpsinitodb
    then
	:
    else
	$ABORT
    fi
fi

# Whether a new installation or an update, the Environment definition
# must be re-read to synchronize with reality.

if getobject false ENV
then
    echo
    pause "Press RETURN to begin installation of all kit components... "
else
    $ABORT
fi

clear

echo
echo "Installing the $PRODUCT ..."
echo

SAMEDIR="    [Using the kit directory...no files will actually be copied]"

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

# Create the production LPS root directory defined by $ENV_LPSROOT.
# If the target directory is the same as the LPSKIT directory, then
# nothing is done; the current state of the directory is left intact.
# A special check is made here, to catch symbolic link situations with
# the LPSKIT and LPSROOT directory paths.
#
# In a modest attempt to be "intelligent" about the creation or current
# state of a new (and critical) LPSROOT directory, note that we:
#
#    -  Simply create the directory (with the proper ownership values) IFF
#       the directory does not currently exist.
#
#    -  If the directory already exists, then we check to see if the special
#       installation flag file exists within that directory.  If it does,
#       then we issue an informational message saying that we are about to
#       overwrite a previous version of the software; otherwise, if the flag
#       doesn't exists, then we assume the directory is being used for
#       something else, so we warn the user and request confirmation for
#       continuing this script.

if linkcheck $LINKCHECKOPTS $ENV_LPSROOT $ENV_LPSKIT
then
    NEWROOT=false
else
    NEWROOT=true
fi

if $NEWROOT
then
    if [ -d $ENV_LPSROOT ]
    then
	if [ -f $ENV_LPSROOT/$INSTFLAG ]
	then
	    echo "[Overwriting a previously installed version of the kit]"
	else
	    if [ `ls -al $ENV_LPSROOT | wc -l` -gt 2 ]
	    then
		$PAGER << END_OF_INPUT
    The primary production directory "$ENV_LPSROOT" already exists,
    but seems to contain something other than a recent version of the
    LPS kit software.

    It is possible that this installation will overwrite something in
    "$ENV_LPSROOT" that is important to your system.  The current
    contents of "$ENV_LPSROOT" are:

    `ls -l $ENV_LPSROOT`

    Continuing this procedure may overwrite one or more of the files
    listed above.
END_OF_INPUT
		if yesno x "Do you want to continue the installation"
		then
		    :
		else
		    $ABORT
		fi
	    fi
	fi
    fi
fi

echo
echo "Initializing the LPS root directory \"$ENV_LPSROOT\" ..."

if $NEWROOT ; then : ; else echo "$SAMEDIR" ; fi

error=false

#
# We set the LPSROOT directory to have owner=daemon and group=0 so
# that Management Client daemons (lpsad processes) can write their
# pid files in this directory.
#
if installdir $ENV_LPSROOT 775 daemon 0
then
    for file in lpsdeinstall lpssetup manpages.map
    do
	path=$ENV_LPSKIT/$file  # Needed for STUPID SCO

	if installfile $path $ENV_LPSROOT 755 $ROOTUID $DAEMONUID
	then
	    :
	else
	    error=true
	fi
    done

    for file in `ls $KITINFO Alist* Vlist*`
    do
	path=$ENV_LPSKIT/$file  # Needed for STUPID SCO

	if installfile $path $ENV_LPSROOT 444 $ROOTUID $DAEMONUID
	then
	    :
	else
	    error=true
	fi
    done
else
    error=true
fi

if $error
then
    echo "    Unable to initialize the \"$ENV_LPSROOT\" directory!"
    echo "    Please do something about this, then re-run this procedure."
    $ABORT
fi

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

# Install key LPS programs and scripts in known, fixed system directories

error=false

echo
echo "Installing key LPS programs and scripts in /etc ..."
$ECHON "    Files: "

if cp $BINDIR/lpsodblist /etc
then
    chmod 755  /etc/lpsodblist
    chown root /etc/lpsodblist
    chgrp bin  /etc/lpsodblist
    $ECHON " lpsodblist"
else
    error=true
fi

if cp $ENV_LPSROOT/lpssetup /etc
then
    chmod 755  /etc/lpssetup
    chown root /etc/lpssetup
    chgrp bin  /etc/lpssetup
    $ECHON " lpssetup"
else
    error=true
fi

if $error
then
    echo "    Unable to copy key LPS programs and scripts to \"/etc/\" !"
    echo "    Please do something about this, then re-run this procedure."
    $ABORT
fi

echo    # The final newline after the successfully installed file list

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

# Ensure certain other critical directories exist with the proper
# protections and ownerships.

echo
echo "Checking to ensure certain critical directories exist..."
$ECHON "  ... $ENV_LPSTMP  "

if [ "$ENV_LPSTMP" != "/tmp" ]	# Do this only for non-default tmp directory
then
    if installdir $ENV_LPSTMP 770 $ROOTUID $DAEMONUID
    then
	:
    else
	echo
	echo "UNABLE TO CREATE DIRECTORY $ENV_LPSTMP"
	echo "Please investigate and repair, then re-run this procedure."
	$ABORT
    fi
fi
echo

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

# Create all other required support directories and install all
# related files.  Various subscripts are used to effect this;
# which subscripts are called depends on the type of kit we're
# dealing with.
#
# If a directory tree of binary executables is to be created,
# then redefine the BINROOT variable now to contain the path
# of the root directory of the tree; otherwise, set BINROOT
# to null to indicate no tree is to be created.
#
# Each installation subscript requires the current values
# of all ENV object variables, as well as the BINDIR and
# BINROOT variables.

echo
echo "Initializing support directories and installing files:"

if [ -f $BINROOT ]   # Did lpsinitodb create a $BINROOT file?
then
    BINROOT="`cat $BINROOT`"
else
    BINROOT=""
fi

expobjvars ENV

error=true

if inst.COMMON   # Install all absolutely common kit stuff first
then
    if $SRCKIT
    then
	script="inst.COMSRC"
    else
	script="inst.COMBIN"
    fi

    if $script   # Install the common Source or Binary Kit-specific stuff
    then
	if $SHKIT
	then
	    if inst.COMSH
	    then
		error=false   # All done for full PC/SH kits
	    fi
	else
	    error=false       # All done for PC-only kits
	fi
    fi
fi

if $error
then
    $ABORT
fi

echo
pause

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

# Install host-level startup capabilities
#
# If setlpsstartup fails, then tell the user that manual hacking of
# the system startup file must be done, but otherwise do NOT bail out
# on the installation.
#
# Also note CAREFULLY that the LPSODBLIST variable is temporarily
# reset to point to "/etc/lpsodblist" to satisfy setlpsstartup.

LPSODBLIST=/etc/lpsodblist  setlpsstartup
if [ $? -ne 0 ]
then
    cat << EOF

    For some reason the attempt to setup your system to automatically
    startup all LPS daemons at system boot time has failed.  This does
    not necessarily imply that the software has not been installed
    correctly thus far; instead, your system may be configured such that
    this installation script can not properly install the necessary
    information to effect the boot-time startup.  Please refer to the
    Installation Guide for further details.
EOF
fi

pause

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

# Install the "man" pages

MANRESULTS=$TMPDIR/manres.$$	# File to receive results description
cat /dev/null > $MANRESULTS	# Ensure it exists and is empty

installman $MANRESULTS		# Ignore errors here

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

# At this point we consider the installation to have been successfully
# performed, so we create a special file in the LPSROOT directory denoting
# this fact.  The existence of this file is tested by other scripts in an
# attempt to intelligently determine whether the kit has been properly
# installed.

echo
pause "Press RETURN to complete the installation... "

cat > $ENV_LPSROOT/$INSTFLAG <<END_OF_INPUT
$PRODUCT installed on `date`.
END_OF_INPUT
chmod a-w $ENV_LPSROOT/$INSTFLAG

# To help the user keep track of the choices made during the creation
# of the LPS Object Database, mail to the designated user the special
# message file created by either the lpsinitodb or lpsupdate script.

subj="Installation of $PRODUCT"
day="`date +%a`"
date="`date '+%h %d'`"
time="`date +%r`"

$ENV_MAILPROG $ENV_MAILOPTS -s "$subj" "$ENV_MAILADMADDRS" << EOF

The $PRODUCT has been successfully
installed on $LOCALHOST on ${day}, ${date}, at ${time}.

You may want to retain this message for future reference to recall
where the various software components have been installed, and to
review the values for the configuration options for operation on
$LOCALHOST.

`cat $ODBMSG`

`cat $MANRESULTS`
EOF

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

# If a software update has been performed, then now is the time to
# restart all clients that were previously shutdown by lpsupdate.

if $NOTUPDATED
then
    :
else
    echo
    pause "Press RETURN to begin restarting all previously defined clients ..."

    # Startup all PC objects

    for obj in `$LPSODBLIST -f $LPSODB -c PC`
    do
	echo "--- Starting Print Client $obj ... "

	if getobject true PC $obj
	then
	    expobjvars PC

	    if upq.$PCTYPE $obj
	    then
		:
	    else
		echo
		echo "Unable to restart the print queue!"
		pause
	    fi
	fi
    done

    # Restart all MC objects

    echo

    for obj in `$LPSODBLIST -f $LPSODB -c MC`
    do
	echo "--- Starting Management Client $obj ... "

	if getobject true MC $obj
	then
	    startMC $obj
	else
	    echo
	    echo "Unable to restart Management Client ${obj}!"
	    pause
	fi
    done

fi

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

# Cleanup our act and get out.
#
# In order to keep the user rolling, we offer to automatically fire up
# the lpssetup script to configure the rest of the system, but only if
# this platform doesn't have problems with exec'ing lpssetup from here.

cleanup

showhelp true "

Installation of the $PRODUCT is complete.

You may now use the \"lpssetup\" script to configure PrintServer
printers, Print Clients and Management Clients.  You should not run
this script again unless you suffer some sort of catastrophic disk
failure, or one or more of the supporting files is in some way
inoperable."

if [ $OSNAME = SCO ]	# SCO can't handle exec'ing another script from here
then
    echo
    echo "Be sure to run the \"lpssetup\" script in order to"
    echo "configure printers, management clients and print clients."
    echo "The lpssetup script is located both in this directory"
    echo "and in the /etc directory."
else
    if yesno y "Do you want to run the \"lpssetup\" script now"
    then
	cd $ENV_LPSROOT
	exec ./lpssetup
    fi
fi

echo
echo "$SCRIPTNAME script completed."
echo

exit 0
#
# Local Variables:
# fill-column:79
# page-delimiter:"^#---"
# End:
