#! /bin/sh
#
# lpsmmc -- Top-level script for managing Management Client objects
#
# @(#)lpsmmc	1.20	LPS_UNX_COM	02/20/95
#
# Copyright 1995   Digital Equipment Corporation, Westford, MA
#
# DESCRIPTION:
#
# This script is used to perform various management tasks for Management
# Clients, such as adding, modifying, removing and listing currently
# defined Management Clients.
#
# This script MUST be executed from the "lpssetup" shell script to ensure
# proper privileges are available, key environment variables are set, and
# the current working directory is properly established.
#
# The current working directory is expected to be LPSROOT directory.
#
# AUTHOR:  Underscore, Inc.
#
###

# Set all script-specific initial variables

ABORT="kill -1 $$"
ATTRLIST="Alist.MC"		# Expected to be in our working dir (LPSROOT)
MAXNAMELEN=9			# Maximum client name length
RESPONSE=""
SCRIPTNAME="lpsmmc"
TITLE="Manage Management Clients"
VARLIST="Vlist.MC"	 	# Expected to be in our working dir (LPSROOT)

OLDLPSODB="$TMPDIR/oldodb.$$"
OUTFILE="$TMPDIR/${SCRIPTNAME}.$$"

INTROTEXT="
$TITLE   ($SCRIPTNAME)

This script performs various management tasks for Management Clients,
allowing you to list all currently defined Clients, add new Clients,
modify existing Clients, remove existing Clients, or control Clients."

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

# Perform the standard top-level management script initialization

. scripts/lpsmxxinit

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

# ckname()
#
# This function determines whether the specified client name exceeds
# the maximum allowed length, or if it contains invalid characters.
#
# Parameters:
#    $1 - The MC name string
#
# Return value:
#    0 - The name is valid
#    1 - The name is too long or contains invalid characters

ckname ()
{
    name=$1

    if [ "$OSTYPE" = "OSF1" -o "$OSTYPE" = "BSD" ]
    then
	leftovers=`echo $name | $TR -d '_A-Za-z0-9-'`
    else
	leftovers=`echo $name | $TR -d '_[A-Z][a-z][0-9]-'`
    fi
 
    if [ -z "$leftovers" ]
    then
	if [ `expr "$name" : '.*'` -le $MAXNAMELEN ]
	then
	    return 0
	fi
    fi

    cat << END_OF_INPUT

    Sorry, but "$name" is an invalid Management Client name.
    A valid name consists of no more than $MAXNAMELEN characters,
    and all characters must be either letters, digits, hyphens or
    underscores.
END_OF_INPUT

    return 1
}

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

# initfile()
#
# This function is used to initialize a target support file.
#
# Parameters:
#    $1 - The path of the target file
#    $2 - The octal protection mode to be applied to the file
#    $3 - Description string
#
# Return value is always 0, implying success.  If the file can not
# be fully initialized, this process is killed via $ABORT.

initfile ()
{
    file=$1
    mode=$2
    desc=$3

    # NOTE: here we FIX the uid/gid values due to the sensitive nature
    #       of the file protections for Management Clients.

    UID="daemon"	# Fixed for all systems
    GID="0"		# Maps to different names on different systems

    problem=""

    if touch $file
    then
	if chmod $mode $file
	then
	    if chown $UID $file && chgrp $GID $file
	    then
		RESPONSE=$file
		return 0
	    fi
	    problem="assigned the proper ownership ($UID/$GID)"
	fi
	problem="properly protected with mode $3"
    fi
    problem="initialized"

    $PAGER << END_OF_INPUT

    The $desc file "$file" could not be ${problem}.
    Please investigate and correct this problem, then re-run
    this procedure.
END_OF_INPUT

    $ABORT
}

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

# mcstartup()
#
# This function is used to either startup a new MC or restart a modified
# MC, and optionally add the "host-level startup" for all MCs on this host.
#
# Parameters:
#    $1 - Flag for start/restart ("start" or "restart")
#    $2 - Name of the MC object to start.
#    $3 - Name of the MC object to stop (required only for "restart").
#
# Return value is 0 if successful, 1 otherwise.

mcstartup ()
{
    XSTART=$1
    MCNAME=$2
    OLDMCNAME=$3

    rc=0		# Return code, assume success until otherwise reset
    nostart=true	# Set false if user says "start/restart"

    if yesno y "Do you want to $XSTART the Management Client now"
    then
	expkitvars
	expobjvars MC

	nostart=false

	if [ "$XSTART" = "restart" ]
	then
	    stopMC $OLDMCNAME	# Ignore errors here
	fi

	if startMC $MCNAME
	then
	    :
	else
	    rc=1	# Indicate a failure condition, fall thru
	    echo
	    echo "    Unable to start the Management Client daemon!"
	    pause
	fi
    fi

    # If the user did not want to start/restart the MC daemon, or if
    # the start/restart failed, offer some instructions on how to
    # manually start the daemon.

    if $nostart || [ $rc -eq 1 ]
    then
	$PAGER << END_OF_INPUT

You can manually start up this Management Client daemon by
executing the following Bourne shell (/bin/sh) command:

    $ENV_LPSBIN/lpsad -M $MCNAME > $logfile 2>&1

If you use the C shell (/bin/csh), then the command would be:

    $ENV_LPSBIN/lpsad -M $MCNAME >& $logfile

Note that you must execute this command while running under
the super-user ("root") account.

END_OF_INPUT
    fi

    # No matter what, perform the check/installation of host-level startup
    #
    # WARNING:  Note the *temporary* explicit setting of the LPSODBLIST
    #           variable below, and that it precedes the actual invocation
    #           of the critical setlpsstartup script.  Read your docs for
    #           details on this command line mechanism if this is strange.

    LPSODBLIST=/etc/lpsodblist setlpsstartup -q

    return $rc
}

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

# addmc()
#
# This function is used to add a new Management Client object.  No arguments
# are expected.
#
# Return value is 0 if successful, 1 otherwise.

addmc ()
{
    clear
    echo
    echo "Add a new Management Client..."

    # Clear all existing MC_* variables

    clearobjvars MC

    # Begin the initialization of this new Client object by getting and
    # validating the object name, and getting the associated printer
    # object name.

    MC_OBJNAME=""

    while true   # Loop until we break
    do
	echo
	$ECHON "What is the name of the new Management Client? "
	read MC_OBJNAME

	if [ -z "$MC_OBJNAME" ]
	then
	    return 0	# NULL response implies go back to the menu
	fi

	# Check the name to ensure it consists of valid characters,
	# and that another MC object by that name doesn't already exist.

	if ckname "$MC_OBJNAME"
	then
	    if objectexists MC $MC_OBJNAME
	    then
		echo
		echo "    A Management Client by that name already exists."
		echo "    Please choose another name, or press RETURN to go"
		echo "    back to the \"$TITLE\" menu."
	    else
		break   # Success, name is OK and no MC object exists
	    fi
	fi
    done

    # Perform required initialization of all object variables that must have
    # "reasonable" default values, most often coming from the ENV object.

    MC_ACCTFILE="$ENV_LPSACCT/${MC_OBJNAME}.cact"   # Derived from MC_OBJNAME
    MC_DEBUGLEVEL="$ENV_DEBUGLEVEL"
    MC_DESCRIPTION="`getobjdesc MC`"
    MC_IOBUFSIZE="$ENV_IOBUFSIZE"		    # Fixed for now
    MC_LASTUPDATED=""
    MC_LOGFILE="$ENV_LPSLOG/${MC_OBJNAME}.elog"	    # Derived from MC_OBJNAME
    MC_LOGLEVEL="$ENV_LOGLEVEL"
    MC_OFFERACCT="Yes"
    MC_OFFERCONFIG="Yes"
    MC_OFFERELOG="Yes"
    MC_ENABLELOG="$MC_OFFERELOG"		    # Tight coupling here!
    MC_PSNAME=""

    # Export the complete set of new MC variables and the existing imported
    # ENV variables for general subprocess use.

    expobjvars MC
    expobjvars ENV

    # Ask the user if configuration should be done "step-by-step" or via
    # a variable menu mechanism, then do perform that request.

    if setMCvars "add" $MC_OBJNAME $VARLIST $ATTRLIST $OUTFILE
    then
	if . $OUTFILE
	then
	    # Set or unset MC_ENABLELOG based the value of MC_OFFERELOG
	    MC_ENABLELOG=$MC_OFFERELOG
	else
	    echo
	    echo "FAILURE to import variables from file \"$OUTFILE\"!"
	    return 1
	fi
    else
	echo
	echo "FAILURE to set all Management Client variables!"
	return 1
    fi

    # Initialize all potentially associated files for the Client

    if boolval $MC_OFFERACCT
    then
	initfile $MC_ACCTFILE 660 "Accounting"
    fi

    if boolval $MC_OFFERELOG || boolval $MC_ENABLELOG
    then
	initfile $MC_LOGFILE 664 "Event log"
    fi

    # Add this new Management Client to the LPS Object Database, startup
    # the Client if the user desires, and perform the tasks needed to
    # ensure automatic startup all defined Mgmt Clients for this host.

    ODBDEF="$TMPDIR/odbdef.$$"

    if mkodbdef MC $ATTRLIST $ODBDEF
    then
	if updateLPSODB $LPSODB add MC $MC_OBJNAME "" $ODBDEF $OLDLPSODB
	then
	    rm -f $ODBDEF   # No longer need this file

	    if mcstartup "start" $MC_OBJNAME
	    then
		$PAGER << END_OF_INPUT

The Management Client "$MC_OBJNAME" should now be ready for use with the
PrintServer printer "$MC_PSNAME" on $LOCALHOST.
END_OF_INPUT
		rm -f $OLDLPSODB $OUTFILE
		return 0
	    fi
	fi
    fi

    # To get here means that something went wrong in either the modification
    # of the LPSODB file, or in the creation of the associated print queue.

    cat << END_OF_INPUT

    Sorry, but the creation of the new Management Client failed for the
    reasons listed above.  See what you can do to fix the problem, then
    try to recreate the Management Client.
END_OF_INPUT

    return 1
}

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

# modmc()
#
# This function is used to modify an existing Management Client object.
# No arguments are expected.
#
# Return value is 0 if successful, 1 otherwise.

modmc ()
{
    clear
    echo
    echo "Modify an existing Management Client..."

    # Clear all existing MC_* variables

    clearobjvars MC

    # Select the MC object to modify, and confirm modification

    if selectobject MC "Which Management Client is to be modified" $OUTFILE ""
    then
	MC_OBJNAME="`cat $OUTFILE`"
    else
	return 0
    fi

    # Extract the current attributes of the client, and save all those
    # values in corresponding "OLDMC_xxx" variables for potential later
    # referencing.

    getobject true MC $MC_OBJNAME

    mkoldobjvars MC

    # Get the (potentially) new name of the client

    while true   # Loop until we break
    do
	echo
	$ECHON "What is the name of the Management Client [${OLDMC_OBJNAME}]? "
	read MC_OBJNAME
	if [ -z "$MC_OBJNAME" -o "$MC_OBJNAME" = "$OLDMC_OBJNAME" ]
	then
	    MC_OBJNAME=$OLDMC_OBJNAME
	    break
	fi

	# Check the name to ensure it consists of valid characters, and
	# that a local print queue by that name doesn't already exist,
	# and that another MC object by that name doesn't already exist.

	if ckname "$MC_OBJNAME"
	then
	    if objectexists MC $MC_OBJNAME
	    then
		echo
		echo "    A Management Client by that name already exists."
		echo "    Please choose another name, or press RETURN to go"
		echo "    back to the \"$TITLE\" menu."
	    else
		break   # Success, name is OK and no MC object exists
	    fi
	fi
    done

    # Export the complete set of new MC variables for general subprocess use

    expobjvars MC

    # Ask the user if modification should be done "step-by-step" or via
    # a variable menu mechanism, then do perform that request.

    if setMCvars "mod" $MC_OBJNAME $VARLIST $ATTRLIST $OUTFILE
    then
	if . $OUTFILE
	then
	    # Set or unset MC_ENABLELOG based the value of MC_OFFERELOG
	    MC_ENABLELOG=$MC_OFFERELOG
	else
	    echo
	    echo "FAILURE to import variables from file \"$OUTFILE\"!"
	    return 1
	fi
    else
	echo
	echo "FAILURE to set all Management Client variables!"
	return 1
    fi

    # Update the LPS Object Database, then restart the Management Client,
    # if the user desires.

    ODBDEF="$TMPDIR/odbdef.$$"

    if mkodbdef MC $ATTRLIST $ODBDEF
    then
	if updateLPSODB $LPSODB replace MC $MC_OBJNAME "$OLDMC_OBJNAME" \
			$ODBDEF $OLDLPSODB
	then
	    rm -f $ODBDEF   # No longer need this file

	    if mcstartup "restart" $MC_OBJNAME $OLDMC_OBJNAME
	    then
		$PAGER << END_OF_INPUT

The Management Client "$MC_OBJNAME" should now be ready for use with the
PrintServer printer "$MC_PSNAME" on $LOCALHOST.
END_OF_INPUT
		rm -f $OLDLPSODB $OUTFILE
		return 0
	    fi
	fi
    fi

    # To get here means that something went wrong in either the modification
    # of the LPSODB file, or in the modification of the associated print
    # queue.

    cat << END_OF_INPUT

    Sorry, but the modification of the Management Client failed for the
    reasons listed above.  See what you can do to fix the problem,
    then try modifying the Management Client again.
END_OF_INPUT

    return 1
}

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

# delmc()
#
# This function is used to remove an existing Management Client (MC) object.
# No arguments are expected.
#
# Return value is 0 if successful, 1 otherwise.

delmc ()
{
    clear
    echo
    echo "Remove an existing Management Client..."

    # Clear all existing MC_* variables

    clearobjvars MC

    # Get the name of the Client to remove, then force the user to
    # confirm the removal.  When confirmed, extract the attributes
    # of the Client from the LPS Object Database.

    if selectobject MC "Which Management Client is to be removed" $OUTFILE ""
    then
	MC_OBJNAME="`cat $OUTFILE`"

	if yesno x "Are you sure you want to remove \"$MC_OBJNAME\""
	then
	    getobject true MC $MC_OBJNAME
	    expobjvars MC
	else
	    return 0
	fi
    else
	return 0
    fi

    # Stop the Management Client if it is running

    stopMC $MC_OBJNAME

    # Remove the Client definition from the LPS Object Database

    if updateLPSODB $LPSODB delete MC "" "$MC_OBJNAME" "" $OLDLPSODB
    then
	rm -f $OLDLPSODB
    else
	return 1
    fi

    # Query the user for disposition of all associated files

    if [ "$MC_ACCTFILE" ]
    then
	if rmfilecheck $MC_ACCTFILE
	then
	    if yesno n "Delete the accounting file"
	    then
		rm $MC_ACCTFILE
	    fi
	else
	    echo "    [Preserving special accounting file: $ACCTFILE]"
	fi
    fi

    if [ "$MC_LOGFILE" ]
    then
	if rmfilecheck $MC_LOGFILE
	then
	    if yesno n "Delete the event log file"
	    then
		rm $MC_LOGFILE
	    fi
	else
	    echo "    [Preserving special event log file: $LOGFILE]"
	fi
    fi

    return 0
}

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

# ctrlmc()
#
# This function is used to start/restart/stop a Management Client object.
# One argument: "start" or "restart" or "stop".
#
# Return value is 0 if successful, 1 otherwise.

ctrlmc ()
{
    ctrl=$1

    case $ctrl in
	start ) Control="Start"
		Controlled="Started"
		script="startMC"
		;;
      restart ) Control="Restart"
		Controlled="Restarted"
		script="restartMC"
		;;
	 stop ) Control="Stop"
		Controlled="Stopped"
		script="stopMC"
		;;
    esac


    clear
    echo
    echo "$Control an existing Management Client..."

    # Get the name of the Client to control, then perform the
    # controlling action.

    if selectobject MC "Which Management Client is to be $Controlled" $OUTFILE ""
    then
	MC_OBJNAME="`cat $OUTFILE`"

	echo

	if $script $MC_OBJNAME
	then
	    :
	else
	    return 1
	fi
    fi

    return 0
}

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

# This is the top-level execution path for this script.  Here we simply
# sit in an infinite loop, requesting a menu number and performing the
# requested procedure.

objdesc=`getobjdesc MC`

while true
do
    echo "
    1) LIST    the names of all defined ${objdesc}s
    2) SHOW    the configuration of a defined $objdesc
    3) EXAMINE the log file of a ${objdesc}

    4) ADD     a new $objdesc definition
    5) MODIFY  an existing $objdesc definition
    6) REMOVE  an existing $objdesc definition

    7) START   an existing $objdesc
    8) RESTART a running $objdesc
    9) STOP    a running $objdesc

   10) STOP    a running lpsbootd daemon
   11) START   a lpsbootd daemon
   12) EXAMINE the lpsbootd log file
   13) CHANGE  booting options for lpsbootd daemon

   14) Return to Main Menu
"
    while true
    do
	$ECHON "Enter one of the above menu numbers [14]: "
	read item
	if checknumrange 1 14 14 "$item"
	then
	    break 1
	fi
    done

    case $item in
	1) listobjects MC          ;;
	2) showobject  MC $VARLIST ;;
        3) showlogfile MC          ;;

	4) addmc                   ;;
	5) modmc                   ;;
	6) delmc                   ;;

	7) ctrlmc start            ;;
	8) ctrlmc restart          ;;
	9) ctrlmc stop             ;;

       10) ctrluniboot stop        ;;
       11) ctrluniboot start       ;;
       12) ctrluniboot showlog     ;;
       13) ctrluniboot change      ;;

	*) break                   ;;
    esac

    echo
    pause "Press RETURN to return to the $TITLE Menu... "
    clear
    echo
    echo $TITLE Menu
done

rm -f $TMPDIR/*.$$
rm -f /tmp/*.$$
rm -f ./*.$$

exit 0

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