#! /sbin/sh
#
# ident "@(#)utsyscfg.sh	1.7 02/05/06 SMI"
#
# Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
#

############################################################################
#
# This script performs one-time setup activities for Sun Ray.  It tailors
# the Sun Ray configuration to match the system's features (eg Xinerama
# capability) and adjusts the system to accomodate Sun Ray quirks.  The
# things that happen here can be done once as the system goes multi-user
# and don't need to be repeated whenever the Sun Ray suite is restarted.
# Anything that needs to be done on every Sun Ray restart belongs
# someplace else, traditionally in the utsvc script.  The script runs
# every time we go up to multi-user, and not just once per boot, because
# some of things we're looking for may have been affected by patches that
# may have been applied in single-user mode.
#
# This script runs fairly early in rc2.d.  On the very first boot we want
# to run before inetd gets started so that we can mark the Sun Ray ports
# 'privileged' before there's any chance of anyone getting into the
# machine and binding a non-root process to those ports.

############################################################################
##
## Function Definitions 
##

# Tell the world (via stdout by historical precedent, although it should
# really be via stderr) how to invoke this script.
#
# Syntax: 'usage'
#
usage() {
	echo "Usage: $0 { start | stop }"
}


# Print a message on stdout if the VERBOSE flag is non-zero.
#
# Syntax: 'vecho text ...'
#
vecho() {
	if [ $VERBOSE -ne 0 ] ; then
		echo "# ${MYNAME}: $@"
	fi
}


# Print the port number corresponding to a given service name, as retrieved
# by 'getent' or, if that fails, by the contents of /etc/services.
#
# Syntax: serv2port servicename
#
serv2port() {

	PORTNUM=`getent services "$1" | awk '{print $2}' | sed 's@/.*@@'`
	if [ -n "$PORTNUM" ] ; then
		echo "$PORTNUM"
		return
	fi

	# nothing found by the configured naming services, try reading
	# /etc/services directly.

        nawk -v SERVICE="$1" '{ \
		sub(/#.*/,""); \
		for (I=1; I<=NF; ++I) { \
			if ($I==SERVICE) { \
				sub(/\/.*/,"",$2); \
				print $2;
				exit; \
			} \
		} \
	}' /etc/services 
}

# Print a list of the Sun Ray port numbers that should be declared
# privileged.  Each line of the table in the inline 'here document'
# contains the name of a Sun Ray service and the port number to be
# used for that service if no port number is returned for that service
# by the service-name-to-port lookup function.
#
# Syntax: privportnums
#
privportnums() {

	while read SERVICE DEFAULTPORT ; do

		# If serv2port can't find a port number for this service we
		# use the default port number held in $DEFAULTPORT
		#
		PORT=`serv2port "$SERVICE"`
		if [ -z "$PORT" ] ; then
			PORT="$DEFAULTPORT"
		fi

		# Emit the (partial) result
		#
		echo "$PORT \c"

	done << EndOfPortList
		utsessiond	7007
		utrcmd		7008
		utauthd		7009
		utauthd-cb	7010
		utdevmgrd	7011
		utdsd		7012
		utscreventd	7013
EndOfPortList

}


# Mark the Sun Ray ports 'privileged' so that they can't be used by a
# non-root user.
#
# Syntax: privports
#
privports() {

        # Mark the Sun Ray daemon ports 'privileged' so that they can't be
        # grabbed by non-root users.  Strictly speaking we only need one
        # UDP port (7009) but we grab both TCP and UDP in all cases, partly
        # for symmetry and partly to leave headroom for feature creep.
        #
        TCP_EXTRA_PRIVS=`/usr/sbin/ndd /dev/tcp tcp_extra_priv_ports`
        UDP_EXTRA_PRIVS=`/usr/sbin/ndd /dev/udp udp_extra_priv_ports`

        for PORT in `privportnums` ; do
            echo "$TCP_EXTRA_PRIVS" | grep -w "$PORT" > /dev/null
            if [ $? -ne 0 ] ; then
		vecho "marking port ${PORT}/tcp privileged"
                /usr/sbin/ndd -set /dev/tcp tcp_extra_priv_ports_add ${PORT}
            else
		vecho "port ${PORT}/tcp is already privileged"
	    fi
            echo "$UDP_EXTRA_PRIVS" | grep -w "$PORT" > /dev/null
            if [ $? -ne 0 ] ; then
		vecho "marking port ${PORT}/udp privileged"
                /usr/sbin/ndd -set /dev/udp udp_extra_priv_ports_add ${PORT}
            else
		vecho "port ${PORT}/udp is already privileged"
            fi
        done
}


# Decide whether this system's X server supports the Xinerama and dpms extensions.
#
# Syntax: xsunoptions
#
xsunoptions() {

	# Examine the X server's usage message.

	XSUNOPTS=`/usr/openwin/bin/Xsun -? 2>&1`

	# If it supports Xinerama then the string 'xinerama' will appear 
	# in the usage report and we record that fact by making sure that 
	# the flag file does not exist.  If the X server does not support
	# Xinerama then we create the flag file.


	FLAGFILE=${SUNWUTETC}/ut_disable_xinerama

	case $XSUNOPTS in

		*xinerama*)
			vecho "Xinerama is supported"
			rm -f ${FLAGFILE}
			;;

		*)
			vecho "Xinerama is not supported"
			(umask 022 && > ${FLAGFILE})
			;;
	esac

	# If X server supports DPMS monitoring, the string "dpms"  will
        # appear in the X server usage message.We create a flag file if
        # it does not support DPMS monitoring else we make sure the flag
        # file does not exist.

	FLAGFILE=${SUNWUTETC}/ut_disable_dpms


	case $XSUNOPTS in
		
		*dpms*)
			vecho "DPMS monitoring is supported"
			rm -f ${FLAGFILE}
			;;
		*)
			vecho "DPMS monitoring is not supported"
			(umask 022 && > ${FLAGFILE})
			;;
	esac
}


############################################################################
##
## Mainline execution starts here 
##

PATH=/bin:/sbin
export PATH

MYNAME=`basename "$0"`

SUNWUTETC=/etc/opt/SUNWut

# We support a couple of undocumented options to help with debugging:
#   -v for verbose, -D for blow-by-blow shell echoing.

VERBOSE=0

while getopts Dv OPTCH; do

	case "$OPTCH" in
		v)	VERBOSE=1
			;;
		D)	set -x
			;;
		*)	usage
			exit 1
			;;
	esac
done
shift `expr "$OPTIND" - 1`

# Validate the (remaining) arguments

if [ $# -ne 1 ] ; then
	usage
	exit 1
fi

case "$1" in

	start)	privports
		xsunoptions
		;;

	stop)	# Nothing for us to do, just fall out of the switch
		;;

	*)	usage
		exit 1
		;;
esac

exit 0
