#!/bin/ksh -p
#
# ident "@(#)utdmsession.ksh	1.18 05/04/01 SMI"
#
# Copyright 2002-2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# utdmsession - Inform the Device Manager of session creation and
#		destruction events.
#
#	Note that since session management needs to manage the
#	per-display session_proc file, we do that here since we
#	already have all the information we need to do that.
#
#    usage:
#
#	utdmsession -c Xdisplay [-z tag]
#	    create DM session based on Xdisplay
#	    -z - optional tag for logging purposes
#
#	utdmsession -d Xdisplay [-z tag]
#	    destroy DM session based on X display
#	    -z - optional tag for logging purposes
#

#exec 2>&1 2>/var/tmp/utdmsession.$$       # Debug
#set -x

MOD="`/bin/basename $0`"
USAGE="usage: $MOD [-c|-d] Xdisplay [-z tag]"
UTMNT_DIRLOCK=".session"

    ID="/usr/bin/id"
    DPY=""
    TAG="$MOD"

    while getopts :c:d:z: action
      do
	case "$action" in
	    c) ACTION="create" ; DPY="$OPTARG" ;;
	    d) ACTION="destroy" ; DPY="$OPTARG" ;;
	    z) TAG="$OPTARG" ;;
	    ?) echo $USAGE ; exit 1 ;;
	esac
      done
    shift $(expr $OPTIND - 1)

    if [ $# -ne 0 -o "$DPY" = "" ] ; then
	echo $USAGE
	exit 2
    fi

    DPYDIR="/var/opt/SUNWut/displays"
    DEVICE_SESSION="$(/bin/sed -n '/^SESSION=.*:/s///p' $DPYDIR/$DPY 2>/dev/null)"

    #
    # If no session, then there's not much we can do.
    # We can be silent about this condition since it's not
    # necessarily an error.
    #
    if [ "$DEVICE_SESSION" = "" ] ; then
	exit 0
    fi

    #
    # OK we've got an X display that maps to a session, now
    # setup the required pointers and actually do the work
    # of talking to the Device Manager about this session.
    #
    SESSION_INFO_DIR="/tmp/SUNWut/session_info"
    SESSION_PROC="/tmp/SUNWut/session_proc/$DPY"
    SESSION_DIR="/tmp/SUNWut/sessions/$DPY"
    TMPFILE="/var/opt/SUNWut/tmp/$MOD.$$"
    
    BASE="/etc/opt/SUNWut/basedir"
    SUNWUTLIB="$BASE/lib"
    UTDMEVENT="$SUNWUTLIB/utdmevent"
    UTSCREVENT="$SUNWUTLIB/utscrevent"

    # timeout in seconds for utdmevent
    UTDMEVENT_TIMEOUT=5

    OS=`uname -s`
    case "$OS" in
    SunOS) 
	# set USER to root if no user
	if [[ -n $USER ]] then
		# get uid & gid in a single call, then save separately
		ID_STRING="$($ID $USER | sed -n 's/uid=\([0-9]*\).* gid=\([0-9]*\).*/\1 \2/p')"
	else
		ID_STRING="$($ID root | sed -n 's/uid=\([0-9]*\).* gid=\([0-9]*\).*/\1 \2/p')"
	fi
	USER_ID="$(echo $ID_STRING | sed -n 's/ [0-9]*//p')"
	GROUP_ID="$(echo $ID_STRING | sed -n 's/[0-9]* //p')"

	TOUCH_CMD="/bin/touch"
	;;

    Linux) 
	# set USER to root if no user
	if [[ -n $USER ]] then
		# separate calls are faster in Linux
		USER_ID="$($ID -u $USER)"
		GROUP_ID="$($ID -g $USER)"
	else
		USER_ID="$($ID -u root)"
		GROUP_ID="$($ID -g root)"
	fi

	TOUCH_CMD="/usr/bin/touch"
	;;

    *)  # undefined OS
	print -u2 "Unable to determine the OS running on this system."
	exit 1
    esac

    # mount root and mount parent directory paths
    MOUNT_DIR="/tmp/SUNWut/mnt"
    if [[ -n $USER ]] then
	USER_MOUNT_DIR="$MOUNT_DIR/$USER"
    else
	# no user, use root
	USER_MOUNT_DIR="$MOUNT_DIR/root"
    fi

    # name of lock file to prevent mnt parent directory deletion when in use
    UTMNT_LOCKFILE=$USER_MOUNT_DIR/$UTMNT_DIRLOCK.$DPY

    #
    # Destroy session information
    #
    if [ "$ACTION" = "destroy" ] ; then

	/bin/rm -f $SESSION_INFO_DIR/$DEVICE_SESSION >/dev/null 2>&1
	/bin/rm -f $SESSION_PROC >/dev/null 2>&1
	/bin/rm -rf $SESSION_DIR >/dev/null 2>&1

	# remove user's mount parent dir if empty
	if [[ -d $USER_MOUNT_DIR ]] then
		# remove first level of children if empty
		for CHILDDIRS in `/bin/ls $USER_MOUNT_DIR`
		do
			MNT_CHILD_DIR=$USER_MOUNT_DIR/$CHILDDIRS
			if [[ -d $MNT_CHILD_DIR ]] then
				/bin/rmdir $MNT_CHILD_DIR >/dev/null 2>&1
			fi
		done
		/bin/rm -f $UTMNT_LOCKFILE >/dev/null 2>&1
		/bin/rmdir $USER_MOUNT_DIR >/dev/null 2>&1
	fi

	# Tell the DM about this session.
	$UTDMEVENT -m "$ACTION $DEVICE_SESSION" -t $UTDMEVENT_TIMEOUT

	if [ -x $UTSCREVENT ]
	then
            	# Tell the smartcard subsystem about this session.
		$UTSCREVENT -d $DPY -z $TAG
	fi

    #
    # Create session information
    #
    else

	#
	# Store the UID and GID into the session info file. The
	# DM uses this information to determine session ownership.
	# set strict umask before creating $SESSION_INFO_DIR/$DEVICE_SESSION
	MY_UMASK="`umask`"
	umask  077
	printf "uid=$USER_ID\ngid=$GROUP_ID\nXID=$DPY\n" \
				> $SESSION_INFO_DIR/$DEVICE_SESSION
	# reset umask
	umask $MY_UMASK

	# Create session directory
	# Remove previous first
	if [[ -d $SESSION_DIR ]] then
		/bin/rm -rf $SESSION_DIR
	fi
	# save current umask and create dir with a strict umask
	MY_UMASK="`umask`"
	umask  077
	TMP_SESSION_DIR="/var/opt/SUNWut/tmp/$MOD.dir.$$"
	/bin/mkdir $TMP_SESSION_DIR 2>/dev/null
	/bin/chown $USER_ID:$GROUP_ID $TMP_SESSION_DIR
	/bin/chmod 0755 $TMP_SESSION_DIR
	mv $TMP_SESSION_DIR $SESSION_DIR

	# if mount root directory does not exist, create it now
	if [[ ! ( -d $MOUNT_DIR ) ]] then
		TMP_PMOUNT_DIR="/var/opt/SUNWut/tmp/$MOD.pmnt.$$"
		/bin/mkdir $TMP_PMOUNT_DIR 2>/dev/null
		/bin/chown root:root $TMP_PMOUNT_DIR
		/bin/chmod 0755 $TMP_PMOUNT_DIR
		mv $TMP_PMOUNT_DIR $MOUNT_DIR
	fi

	# create user's mount parent directory if it does not exist
	# current umask is still good
	if [[ ! ( -d $USER_MOUNT_DIR ) ]] then
		TMP_UMOUNT_DIR="/var/opt/SUNWut/tmp/$MOD.umnt.$$"
		/bin/mkdir $TMP_UMOUNT_DIR 2>/dev/null
		/bin/chown $USER_ID:$GROUP_ID $TMP_UMOUNT_DIR
		/bin/chmod 0700 $TMP_UMOUNT_DIR
		mv $TMP_UMOUNT_DIR $USER_MOUNT_DIR
	fi

	# create directory lock file for this session, only if user logged in
	if [[ -n $USER ]] then
		$TOUCH_CMD $UTMNT_LOCKFILE
	fi

	# create link from session dir to users mount dir
	SESSION_MNT_LINK="$SESSION_DIR/mnt"
	/bin/ln	-s $USER_MOUNT_DIR $SESSION_MNT_LINK

	# reset umask
	umask $MY_UMASK

	#
	# Store the user for session management.
	# The session_proc file must already been created by
	# Xsetup.
	# Note that this is not strictly related to the DM, but
	# we are here and already have all the information
	# we need to do this (SESSIONID, UID, etc...).
	#
	# Remove any existing UID that was in the file - this
	# UID was put here by a previous invocation of this script.
	#
	# It's OK if the session_proc file doesn't exist, since
	# we could be being called to create a new session before
	# the X files have been run (i.e. from utdtsession). In this
	# case, just create a new session_proc file and add the
	# current UID to that file.
	#
	/bin/grep -v "^uid=" $SESSION_PROC >$TMPFILE 2>/dev/null
	mv $TMPFILE $SESSION_PROC

	/bin/grep "^uid=" $SESSION_INFO_DIR/$DEVICE_SESSION >> $SESSION_PROC

	# Tell the DM about this session.
	$UTDMEVENT -m "$ACTION $DEVICE_SESSION" -t $UTDMEVENT_TIMEOUT

	if [ -x $UTSCREVENT ]
	then
		# Tell the smartcard subsystem about this session.
		$UTSCREVENT -c $DPY -z $TAG
	fi
    fi

exit 0
