#
#*******************************************************************************
#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#*******************************************************************************
#
# ident "$Id$ SMI"
#

KIOSK_PREFIX=/opt/SUNWkio
KIOSK_DEFAULT_CONFIG_DIR=/etc/opt/SUNWkio
KIOSK_DEFAULT_VAR_DIR=/var/opt/SUNWkio
KIOSK_DEFAULT_APPS_DIR=$KIOSK_DEFAULT_CONFIG_DIR/applications
KIOSK_DEFAULT_SESSIONS_DIR=$KIOSK_DEFAULT_CONFIG_DIR/sessions
KIOSK_DEFAULT_PROTOS_DIIR=$KIOSK_DEFAULT_CONFIG_DIR/prototypes
KIOSK_DEFAULT_TMP_DIRS="/tmp /var/tmp"    

KIOSK_RESULT_SUCCESS=0
KIOSK_RESULT_FAILED=1

KIOSK_FALSE=0
KIOSK_TRUE=1

# Determine where logger is - distros don't agree
KIOSK_LOGGER_=
if [ -x /usr/bin/logger ] ; then 
	KIOSK_LOGGER_=/usr/bin/logger
elif [ -x /bin/logger ] ; then 
	KIOSK_LOGGER_=/bin/logger
else
	# No logger found - just don't log
	echo 1>&2 "kiosk:utils: Cannot log to syslog - no logger found"
	KIOSK_LOGGER_=/bin/true
fi	

#
## Do a full clean up for a Kiosk user. This includes
##  - kill off any processes owned by the user
##  - remove any residual temporary files owned by the user
##  - remove the user's home directory
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the name of the user for which the clean up should be done
##
## param _inHome
##  the home directory of the user for which the clean up should be done
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
## Note: this function continues thru. each of the stages mentioned above
##       regardless of an error ocurring
#
cleanup()
{
 _inModule=$1
 _inUser=$2
 _inHome=$3

 theRC=$KIOSK_RESULT_SUCCESS
 cleanupProcesses $_inModule $_inUser
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  theRC=$KIOSK_RESULT_FAILED
 fi
 cleanupHome $_inModule $_inHome
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  theRC=$KIOSK_RESULT_FAILED
 fi
 cleanupTempFiles $_inModule $_inUser
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  theRC=$KIOSK_RESULT_FAILED
 fi
 return $theRC
}

#
## Remove the home directory of a Kiosk user
##
## param _inModule
##  the module name of the calling module
##
## param _inHome
##  the home directory to be removed
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
cleanupHome()
{
 _inModule=$1
 _inHome=$2

 logDebug -m "$_inModule" -l "removing Kiosk home directory '$_inHome'"

 if [ -d "$_inHome" ] ; then
 /bin/rm -rf "$_inHome"
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
           -l "Error: failed to remove Kiosk home directory '$_inHome'"
  return $KIOSK_RESULT_FAILED
 else
  logDebug -m "$_inModule" \
     	   -l "Success: removed Kiosk home directory '$_inHome'"
  return $KIOSK_RESULT_SUCCESS
 fi
else
  logDebug -m "$_inModule" \
      	   -l "Success: Kiosk home directory '$_inHome' does not exist"
  return $KIOSK_RESULT_SUCCESS
fi
}

#
## Kill processes for a given user
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the name of the user whose processes should be killed
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
cleanupProcesses()
{
 _inModule=$1
 _inUser=$2
 msg=

 logDebug -m "$_inModule" -l "killing processes for user '$_inUser'"

 pids=`/usr/bin/pgrep -U "$_inUser"`
 if [ -n "$pids" ] ; then
  if [ -x /usr/bin/prun ] ; then
   /usr/bin/prun $pids
  else
   kill -CONT $pids
  fi
  msg="`/usr/bin/pkill -U $_inUser 2>&1`" 
 fi

 if [ $? -eq 0 ] ; then
  logDebug -m "$_inModule" -l "Success: killed processes for user '$_inUser'"
  return $KIOSK_RESULT_SUCCESS
 else
  logDebug -m "$_inModule" \
           -l "Error: failed to kill processes for user '$_inUser': $msg"
  return $KIOSK_RESULT_FAILED
 fi
}

#
## Remove any temporary files & directories owned by a given Kiosk user
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the user whose temporary files should be removed
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
## Note: removing parameters in KIOSK_TMP_DIRS
#
cleanupTempFiles()
{
 _inModule=$1
 _inUser=$2

 logDebug -m "$_inModule" \
      -l "removing temporary files and directories for user '$_inUser'"
 /usr/bin/find ${KIOSK_TMP_DIRS:-$KIOSK_DEFAULT_TMP_DIRS} -user $_inUser \
 					! -type d -exec /bin/rm -f {} \;
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
           -l "Error: failed to remove temporary files for user '$_inUser'"
  return $KIOSK_RESULT_FAILED
 fi
 /usr/bin/find ${KIOSK_TMP_DIRS:-$KIOSK_DEFAULT_TMP_DIRS} -user $_inUser \
 					-depth -exec /bin/rmdir {} \;
 if [ $? -ne 0 ] ; then
  # Don't fail, if we leave directories: 
  # They might be shared-use (like .ICE-unix) and 
  # directory existence should not be security relevant  
  logDebug -m "$_inModule" \
           -l "Warning: failed to remove temporary directories for user '$_inUser'"
  return $KIOSK_RESULT_FAILED
 else
  logDebug -m "$_inModule" \
       -l "Success: removed temporary files and directories for user '$_inUser'"
  return $KIOSK_RESULT_SUCCESS
 fi
}

#
## Create home directory for a Kiosk user and "install" the user prototype
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the user whose home directory should be created
##
## param _inGroup
##  the primary group of $_inUser
##
## param _inHome
##  the home directory to be created
##
## param _inPrototype
##  the user prototype to be "installed"
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
createHome()
{
 _inModule=$1
 _inUser=$2
 _inGroup=$3
 _inHome=$4
 _inProto=$5

 logDebug -m "$_inModule" \
      -l "creating home directory '$_inHome' for user '$_inUser'"

 if [ -d $_inHome ] ; then
  logDebug -m "$_inModule" -l "Error: directory '$_inHome' already exists"
  return $KIOSK_RESULT_FAILED
 fi

 /bin/mkdir -p $_inHome && chown $_inUser:$_inGroup $_inHome && chmod 755 $_inHome
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" -l "Error: failed to create directory '$_inHome'"
  return $KIOSK_RESULT_FAILED
 fi

 installPrototype $_inModule $_inProto $_inHome $_inUser $_inGroup
}

#
## Dot a file, checking if it can be read first and reporting any errors
##
## param _inModule
##  the module name of the calling module 
##
## param _inFile
##  the file to be dotted
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED if _inFile can't be read or 
##			       if dotting _inFile fails
##
## Note: parameters are not checked
#
dotFile()
{
 _inModule=$1
 _inFile=$2

 logDebug -m "$_inModule" -l "dotting file '$_inFile'"
 if [ ! -r "$_inFile" ] ; then
  logDebug -m "$_inModule" -l "Error: can't read file '$_inFile'"
  return $KIOSK_RESULT_FAILED
 fi
 . "$_inFile"
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" -l "Error: failed to dot file '$_inFile'"
  return $KIOSK_RESULT_FAILED
 else
  logDebug -m "$_inModule" -l "Success: dotted file '$_inFile'"
  return $KIOSK_RESULT_SUCCESS
 fi
}


#
## Normalize a display name to a standard form
##
## param _inModule
##  the module name of the calling module 
##
## param _inDisplay
##  the file to be dotted
##
## outputs the normalized display name or 
##         nothing, if _inDisplay is not a valid display name
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED if _inDisplay is not a valid display name
##
#
normalizeDisplay()
{
 _inDisplay=$1
 
# Normalize host part
 case $_inDisplay in
  localhost:*) theReducedDisplay=`echo $_inDisplay | /bin/sed 's/^localhost//'` ;;
  unix:*)      theReducedDisplay=`echo $_inDisplay | /bin/sed 's/^unix//'` ;;
  *:*)	       theReducedDisplay=$_inDisplay ;;
  *)	       return $KIOSK_RESULT_FAILED ;; # invalid display name
 esac 

#strip screen part if present and check that the display number is numeric 
 echo $theReducedDisplay | 
 	/bin/sed -n \
		 -e '/^.*:[0-9][0-9]*$/p' \
		 -e 's/^\(.*:[0-9][0-9]*\)\.[0-9][0-9]*/\1/p' 
}

#
## Create an application descriptor based on an executable
##
## This function accepts the path to an executable and creates an application
## descriptor reflecting same. The resulting descriptor can be "launched"
## using the kioskapplaunch utility.
##
## param _inModule
##  the module name of the calling module
##
## param _inExec
##  the path to the executable for which a descriptor should be created
##
## param _inDesc
##  the path to the descriptor to be created
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED if _inFile can't be read or
##                 if dotting _inFile fails
##
## Note: parameters are not checked
## Note: the parent directory of _inDesc is automatically created if it doesn't
##       already exist
#
execToApplicationDescriptor()
{
 _inModule=$1
 _inExec=$2
 _inDesc=$3

 logDebug -m "$_inModule" \
       -l "creating descriptor '$_inDesc' for executable '$_inExec'"
 /bin/mkdir -p `/usr/bin/dirname "$_inDesc"` &&
 cat << ! > "$_inDesc"
  KIOSK_APP_EXEC="$_inExec"
  KIOSK_APP_LABEL="`/bin/basename "$_inExec"`"
  KIOSK_APP_DESCRIPTION="Temporary descriptor created for executable '$_inExec'"
!
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
    -l "Error: failed to create descriptor '$_inDesc' for executable '$_inExec'"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Install a specified prototype in a specified location
##
## param _inModule
##  the module name of the calling module
##
## param _inPrototypeName
##  the prototype name ( as it appears in a Session Descriptor )
##
## param _inTargetDir
##  the directory where the prototype should be "installed"
##
## param _inUser
##  the user who should own the resulting files
##
## param _inGroup
##  the group that should own the resulting files
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
installPrototype()
{
 _inModule=$1
 _inPrototypeName=$2
 _inTargetDir=$3
 _inUser=$4
 _inGroup=$5

 logDebug -m "$_inModule" \
          -l "installing prototype '$_inPrototypeName' for user '$_inUser'"

 if [ ! -d "$_inTargetDir" ] ; then
  logDebug -m "$_inModule" \
           -l "Error: target directory '$_inTargetDir' doesn't exist"
  return $KIOSK_RESULT_FAILED
 fi

 isAbsolutePath $_inPrototypeName
 if [ $? -eq $KIOSK_TRUE ] ; then
  _thePrototyeDir=$_inPrototypeName
 else
  _thePrototyeDir=$KIOSK_PROTOS_DIR/$_inPrototypeName
 fi
 if [ ! -d "$_thePrototyeDir" ] ; then
  logDebug -m "$_inModule" \
           -l "Error: prototype directory '$_thePrototyeDir' doesn't exist"
  return $KIOSK_RESULT_FAILED
 fi
 
 ( cd "$_thePrototyeDir" && tar cf - . |
  ( cd "$_inTargetDir" && tar xf - ) && 
      /bin/chown -R $_inUser:$_inGroup "$_inTargetDir")
 if [ $? -eq 0 ] ; then
  logDebug -m "$_inModule" -l "Success: installed prototype"
  return $KIOSK_RESULT_SUCCESS
 else
  logDebug -m "$_inModule" -l "Error: failed to install prototype"
  return $KIOSK_RESULT_FAILED
 fi
}

#
## Load an Application Descriptor
##
## param _inModule
##  the module name of the calling module
##
## param _inName
##  the name of the application for which the Descriptor should be loaded
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
## Note: all known Kiosk application settings are unset before dotting the
##       relevant Application Descriptor. This allows the function to be
##       called multiple times while ensuring that settings from a previous
##       call ( for a different application ) are not inherited. The list of
##       settings handled in this way is ...
##       KIOSK_APP_EXEC, KIOSK_APP_ARGS, KIOSK_APP_PROTOTYPE
#
loadApplicationDescriptor()
{
 _inModule=$1
 _inAppName=$2

 logDebug -m "$_inModule" \
          -l "loading Application Descriptor for '$_inAppName'"


 unset KIOSK_APP_EXEC KIOSK_APP_ARGS KIOSK_APP_PROTOTYPE

 #
 ## Figure out Application Descriptor file based on $_inAppName
 #
 _theAppDescriptorFile=`appNameToDescriptorFile "$_inAppName"`

 #
 ## Load the Application Descriptor
 #
 dotFile "$_inModule" "$_theAppDescriptorFile"
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  logDebug -m "$_inModule" -l "Error: failed to load Application Descriptor"
  return $KIOSK_RESULT_FAILED
 else
  logDebug -m "$_inModule" -l "Success: loaded Application Descriptor"
  return $KIOSK_RESULT_SUCCESS
 fi
}

#
## Load the Session Descriptor for a given display
##
## param _inModule
##  the module name of the calling module
##
## param _inDisplay
##  the display for which the Session Descriptor should be loaded
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
loadSessionConfiguration()
{
 _inModule=$1
 _inDisplay=$2

 logDebug -m "$_inModule" \
          -l "loading Session Configuration for display '$_inDisplay'"

 #
 ## Load the Kiosk Session Configuration first to figure out KIOSK_ENABLED and
 ## KIOSK_SESSION
 #
 dotFile "$_inModule" $KIOSK_VAR_DIR/config/$_inDisplay
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  return $KIOSK_RESULT_FAILED
 fi

 #
 ## Don't continue any further if Kiosk is not enabled
 #
 if [ "x$KIOSK_ENABLED" != "xyes" ] ; then
  logDebug -m "$_inModule" \
           -l "Error: Kiosk is not enabled for display '$_inDisplay'"
 fi

 #
 ## Next verify that KIOSK_SESSION has been set
 #
 if [ -z "$KIOSK_SESSION" ] ; then
  logDebug -m "$_inModule" -l "Error: \$KIOSK_SESSION not specified"
  return $KIOSK_RESULT_FAILED
 fi

 #
 ## Figure out Kiosk Session Descriptor file based on $KIOSK_SESSION
 #
 _theSessionDescriptorFile=`sessionNameToDescriptorFile "$KIOSK_SESSION"`

 #
 ## Set KIOSK_SESSION_DIR relative to Kiosk Session Descriptor file,
 ## if it wasn't set before and exists
 #
 if [ -z "$KIOSK_SESSION_DIR" ] ; then
   _theSessionDir=`echo $_theSessionDescriptorFile | 
		   /bin/sed 's/\.[A-Za-z]*$//'`
   if [ -d "$_theSessionDir" ] ; then
     KIOSK_SESSION_DIR="$_theSessionDir"
   fi     
 fi		     

 #
 ## Next, load the Kiosk Session Descriptor
 #
 dotFile "$_inModule" "$_theSessionDescriptorFile"
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  logDebug -m "$_inModule" -l "Error: failed to load Session Descriptor"
  return $KIOSK_RESULT_FAILED
 fi

 #
 ## Finally, to allow Kiosk Session configuration to  
 ## override the Kiosk Session Descriptor, we load 
 ## the Session configuration again.
 #
 dotFile "$_inModule" $KIOSK_VAR_DIR/config/$_inDisplay
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  return $KIOSK_RESULT_FAILED
 fi
 logDebug -m "$_inModule" \
          -l "Success: Session Configuration for display '$_inDisplay' loaded"
 return $KIOSK_RESULT_SUCCESS
}

#
## Some logging functions which simply wrap the syslog function
#
logDebug()
{
 if [ "${KIOSK_DEBUG:-0}" != "0" ] ; then
     syslog -p user.debug "$@"
 fi 	 
}
logError()
{
 syslog -p user.error "$@"
}
logInfo()
{
 syslog -p user.info "$@"
}
logWarning()
{
 syslog -p user.warn "$@"
}

# 
## Make the KIOSK_DYN_DIR directory
#
## param _inModule
##  the module name of the calling module
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
makeKioskDynDir() 
{
 _inModule=$1

 # Set up the /var/run/opt directory with proper attributes
 theVarRunOptDir=`/usr/bin/dirname $KIOSK_DYN_DIR`
 if [ ! -d $theVarRunOptDir ] ; then
  theOS=`uname`
  if [ "$theOS" = "Linux" ] ; then
   theSysdirGroup=root
  else
   theSysdirGroup=sys
  fi
  /bin/mkdir -m 755 $theVarRunOptDir 
  if [ $? -ne 0 ] ; then
   logDebug -m "$_inModule" \
              -l "Error: failed to create directory '$theVarRunOptDir'"
   return $KIOSK_RESULT_FAILED
  fi
  # Set correct group ownership
  /bin/chgrp $theSysdirGroup $theVarRunOptDir
  if [ $? -ne 0 ] ; then
   logDebug -m "$_inModule" \
              -l "Error: failed to set up directory '$theVarRunOptDir'"
   rmdir "$theVarRunOptDir"	      
   return $KIOSK_RESULT_FAILED
  fi
 fi
 # KIOSK_DYN_DIR should be a child of /var/run/opt
 # but to be safe, we mkdir -p anyways
 if [ ! -d $KIOSK_DYN_DIR ] ; then
  /bin/mkdir -p -m 755 $KIOSK_DYN_DIR
  if [ $? -ne 0 ] ; then
   logDebug -m "$_inModule" \
	    -l "Error: failed to create directory '$KIOSK_DYN_DIR'"
   return $KIOSK_RESULT_FAILED
  fi 
  logDebug -m "$_inModule"  -l "Success: created directory '$KIOSK_DYN_DIR'"
 fi
 return $KIOSK_RESULT_SUCCESS 
}

#
## Create the dynamic data dir for a given session 
## (identified by the user name)
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the user for whom the dir should be created
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
makeDynDir()
{
 _inModule=$1
 _inUser=$2

 makeKioskDynDir "$_inModule"
 if [ $? -ne 0 ] ; then
  return $KIOSK_RESULT_FAILED
 fi 

 theSessionsDynDir=$KIOSK_DYN_DIR/sessions
 theSessionUserDynDir=$theSessionsDynDir/$_inUser
 if [ ! -d $theSessionUserDynDir ] ; then
  if [ ! -d $theSessionsDynDir ] ; then
   /bin/mkdir -m 755 $theSessionsDynDir 
   if [ $? -ne 0 ] ; then
    logDebug -m "$_inModule" -l "Error: failed to create directory '$theSessionsDynDir'"
    return $KIOSK_RESULT_FAILED
   fi
   logDebug -m "$_inModule"  -l "Success: created directory '$theSessionsDynDir'"
  fi 

  /bin/mkdir -m 755 $theSessionUserDynDir 
  if [ $? -ne 0 ] ; then
   logDebug -m "$_inModule" -l "Error: failed to create directory '$theSessionUserDynDir'"
   return $KIOSK_RESULT_FAILED
  fi
  logDebug -m "$_inModule"  -l "Success: created directory '$theSessionUserDynDir'"
 fi 
 return $KIOSK_RESULT_SUCCESS 
}

#
## Remove the dynamic data dir for a given user
##
## param _inModule
##  the module name of the calling module
##
## param _inUser
##  the user for whom the dir should be created
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
removeDynDir()
{
 _inModule=$1
 _inUser=$2

 theSessionsDynDir=$KIOSK_DYN_DIR/sessions
 theSessionUserDynDir=$theSessionsDynDir/$_inUser

 /bin/rm -rf $theSessionUserDynDir
 if [ $? -ne 0 ] ; then
  logDebug -m $_inModule -l "Error: failed to remove directory '$theSessionUserDynDir'"
  return $KIOSK_RESULT_FAILED
 fi
 logDebug -m $_inModule -l "Success: removed directory '$theSessionUserDynDir'"

 # Also remove $theSessionDynDir if it has become empty (ignore result)
 /bin/rmdir $theSessionsDynDir 2>/dev/null &&
     logDebug -m $_inModule -l "Success: removed directory '$theSessionsDynDir'"

 return $KIOSK_RESULT_SUCCESS
}

#
## Iterate over the configured Kiosk Application List, calling the configured
## Kiosk Session specific application launcher for each entry found.
## The intention is that Kiosk Primary Sessions don't need to have any
## knowledge of the format of application lists and the Kiosk framework doesn't
## need to have any knowledge of primary session specific requirements for
## configuring, launching etc. Kiosk applications.
##
## param _inModule
##  the module name of the calling module
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
processApplicationList()
{
 _inModule=$1
 
 logDebug -m "$_inModule" -l "processing application list"
 if [ -z "$DISPLAY" ] ; then
  logDebug -m "$_inModule" -l "Error: \$DISPLAY is not set"
  return $KIOSK_RESULT_FAILED
 fi

 loadSessionConfiguration "$_inModule" $DISPLAY
 if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
  logDebug -m "$_inModule" -l "Error: failed to load Session Descriptor"
  return $KIOSK_RESULT_FAILED
 fi
 
 if [ -z "$KIOSK_SESSION_APPLIST" ] ; then
  return $KIOSK_RESULT_SUCCESS
 fi
 
 if [ -z "$KIOSK_SESSION_APPLAUNCHER" ] ; then
  logDebug -m "$_inModule" -l "Error: \$KIOSK_SESSION_APPLAUNCHER is not set"
  return $KIOSK_RESULT_FAILED
 fi
 
 if [ ! -x "$KIOSK_SESSION_APPLAUNCHER" ] ; then
  logDebug -m "$_inModule" \
     -l "Error: Kiosk application launcher '$KIOSK_SESSION_APPLAUNCHER' does not exist or cannot be executed"
  return $KIOSK_RESULT_FAILED
 fi
 
 _theAppListFile=`appListNameToAppListFile "$KIOSK_SESSION_APPLIST"`
 if [ ! -f "$_theAppListFile" ] ; then
  logDebug -m "$_inModule" \
     -l "Error: the Kiosk application list file '$_theAppListFile' was not found"
  return $KIOSK_RESULT_FAILED
 fi
 /bin/cat "$_theAppListFile" |
  processApplicationListFile $_inModule "$KIOSK_SESSION_APPLAUNCHER"
}

#
## Execute the configured Kiosk Application Launcher for each entry in the
## configured Kiosk Application List
##
## param _inModule
##  the module name of the calling module
##
## param _inAppLauncher
##  the Kiosk Application Launcher
##
## returns KIOSK_RESULT_SUCCESS on success
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
processApplicationListFile()
{
 _inModule=$1
 _inAppLauncher=$2

 theRC=$KIOSK_RESULT_SUCCESS
 while read _inAppListEntry ; do
  #
  ## Skip blank lines
  #
  if [ -n "$_inAppListEntry" ] ; then
   _theType=`echo $_inAppListEntry    | /usr/bin/awk 'BEGIN{ FS=":" } { print $1 }'`
   _theAppName=`echo $_inAppListEntry | /usr/bin/awk 'BEGIN{ FS=":" } { print $2 }'`
   _theMode=`echo $_inAppListEntry    |
     /usr/bin/awk 'BEGIN{ FS=":" } { print substr( $3, 0, index($3,";" )-1 ) }'`
   _theArgs=`echo $_inAppListEntry    | /usr/bin/awk 'BEGIN{ FS=";" } { print $2 }'`
   if [ -z "$_theType" -o -z $"_theAppName" -o -z $"_theMode" ] ; then
    theRC=$KIOSK_RESULT_FAILED
    logDebug -m "$_inModule" \
             -l "Error: invalid application list entry '$_inAppListEntry' found"
    break
   fi
   "$_inAppLauncher" "$_theType" "$_theAppName" "$_theMode" "$_theArgs"
   if [ $? -ne 0 ] ; then
    theRC=$KIOSK_RESULT_FAILED
    logDebug -m "$_inModule" \
            -l "Error: command '$_inAppLauncher $_theType $_theAppName $_theMode $_theArgs' failed"
    break
   fi
  fi
 done
 return $theRC
}

#
## The next 4 functions are used to convert session or application names into
## descriptor paths and application list names to application list file paths
#
isAbsolutePath()
{
 _inName=$1
 _isAbsolute=`echo $_inName |
	/usr/bin/awk '{
		if ( index( $0, "/" ) == 1 )
		{
			print "true"
		}
		else
		{
			print "false"
		}
	}'`
 if [ $_isAbsolute = "true" ] ; then
  return $KIOSK_TRUE
 else
  return $KIOSK_FALSE
 fi
}
appListNameToAppListFile()
{
 _inName=$1
 isAbsolutePath "$_inName"
 if [ $? -eq $KIOSK_TRUE ] ; then
  echo $_inName
 else
  echo $KIOSK_APPS_DIR/$_inName.list
 fi
}
appNameToDescriptorFile()
{
 _inName=$1
 isAbsolutePath "$_inName"
 if [ $? -eq $KIOSK_TRUE ] ; then
  echo $_inName
 else
  echo $KIOSK_APPS_DIR/$_inName.conf
 fi
}
sessionNameToDescriptorFile()
{
 _inName=$1
 isAbsolutePath "$_inName"
 if [ $? -eq $KIOSK_TRUE ] ; then
  echo $_inName
 else
  echo $KIOSK_SESSIONS_DIR/$_inName.conf
 fi
}

#
## Launch a critical application
##
## param _inModule
##  the module name of the calling module
##
## param _inApp
##  the application to be registered
##
## param _inArgs
##  the application arguments
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
launchCriticalApp()
{
 _inModule=$1
 shift

 if [ -z "$USER" ] ; then
  logDebug -m "$_inModule" -l "Error: \$USER not specified"
  return $KIOSK_RESULT_FAILED
 fi
 
 launchCriticalAppForUser "$_inModule" "$USER" "$@"
}

#
## Launch a critical application
##
## param _inModule
##  the module name of the calling module
##
## param _inApp
##  the application to be registered
##
## param _inArgs
##  the application arguments
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
launchCriticalAppForUser()
{
 _inModule=$1
 _inUser=$2    
 _inApp=$3
 shift ; shift ; shift

 logDebug -m "$_inModule" -l "launching critical application '$_inApp $@'"

 theSessionUserDynDir=$KIOSK_DYN_DIR/sessions/$_inUser
 $KIOSK_PREFIX/lib/kioskcrit $theSessionUserDynDir/kioskcritd "$_inApp" $@
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
           -l "Error: failed to launch critical application '$_inApp $@'"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Start the Critical Applications Monitor
##
## param _inModule
##  the module name of the calling module
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
startCriticalAppsMonitor()
{
 _inModule=$1

 logDebug -m "$_inModule" -l "starting the Critical Applications Monitor" 

 if [ -z "$USER" ] ; then
  logDebug -m "$_inModule" -l "Error: \$DISPLAY or \$USER not specified"
  return $KIOSK_RESULT_FAILED
 fi

 theSessionUserDynDir=$KIOSK_DYN_DIR/sessions/$USER
 theKioskcritDir="$theSessionUserDynDir/kioskcritd"
 /bin/rm -rf "$theKioskcritDir" && 
 	/bin/mkdir -p -m 700 "$theKioskcritDir" && 
	/bin/chown $USER "$theKioskcritDir"
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
           -l "failed to create directory '$theKioskcritDir'"
  return $KIOSK_RESULT_FAILED
 fi
 $KIOSK_PREFIX/lib/kioskcritd "$theKioskcritDir" $USER
 if [ $? -ne 0 ] ; then
  logDebug -m "$_inModule" \
      	   -l "failed to start the Critical Applications Monitor"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Stop the Critical Applications Monitor
##
## param _inModule
##  the module name of the calling module
##
## returns KIOSK_RESULT_SUCCESS if successful
##         KIOSK_RESULT_FAILED otherwise
##
## Note: parameters are not checked
#
stopCriticalAppsMonitor()
{
 _inModule=$1

 logDebug -m "$_inModule" -l "stopping the Critical Applications Monitor"

 if [ -z "$USER" ] ; then
  logDebug -m "$_inModule" -l "Error: \$USER not specified"
  return $KIOSK_RESULT_FAILED
 fi

 theSessionUserDynDir=$KIOSK_DYN_DIR/sessions/$USER
 thePID=`/bin/cat $theSessionUserDynDir/kioskcritd/kioskcritd.pid`
 if [ $? -eq 0 ] ; then
  kill $thePID
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Log a message to syslog ( by wrapping logger )
##
## Usage: -p <priority> -m <module> -l <message>
#
syslog()
{
 OPTIND=1
 _thePriority=user.info
 _theModule=kiosk
 _theMessage=
 while getopts p:m:l: inOpt ; do
  case $inOpt in
   p)  _thePriority="$OPTARG";;
   m)  _theModule="$OPTARG";;
   l)  _theMessage="$OPTARG";;
   \?) $KIOSK_LOGGER_ -i -p user.error \
		      -t "$_theModule" "invalid syslog argument specified"
       OPTIND=1
       return $KIOSK_RESULT_FAILED
  esac
 done
 $KIOSK_LOGGER_ -i -p "$_thePriority" -t "$_theModule" "$_theMessage"
 OPTIND=1
 return $KIOSK_RESULT_SUCCESS
}

#
## Setup basic Kiosk environment and sanity check
#
dotFile kiosk:utils $KIOSK_DEFAULT_CONFIG_DIR/kioskrc
if [ $? -ne $KIOSK_RESULT_SUCCESS ] ; then
 return $KIOSK_RESULT_FAILED
fi
KIOSK_CONFIG_DIR=${KIOSK_CONFIG_DIR:-$KIOSK_DEFAULT_CONFIG_DIR}
KIOSK_VAR_DIR=${KIOSK_VAR_DIR:-$KIOSK_DEFAULT_VAR_DIR}
KIOSK_APPS_DIR=${KIOSK_APPS_DIR:-$KIOSK_DEFAULT_APPS_DIR}
KIOSK_SESSIONS_DIR=${KIOSK_SESSIONS_DIR:-$KIOSK_DEFAULT_SESSIONS_DIR}
KIOSK_PROTOS_DIR=${KIOSK_PROTOS_DIR:-$KIOSK_DEFAULT_PROTOS_DIR}
KIOSK_DYN_DIR=/var/run/opt/SUNWkio
KIOSK_TMP_DIRS=${KIOSK_TMP_DIRS:-$KIOSK_DEFAULT_TMP_DIRS}
