#!/bin/sh
#
# ident "@(#)$Id$ Oracle"
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#

if [ -n "$KIOSK_PARAM_DEBUG" ] ; then
  set -x
fi

# Sanitize environment
PATH=/usr/bin:/bin
export PATH

short_usage()
{
 echo 1>&2 "Usage: "
 echo 1>&2 "    kioskparam <options> [<pattern> ...]"
 echo 1>&2 "    kioskparam -h"
 exit 1
}

show_usage()
{
# TODO implement command-specific help  
cat 1>&2 <<!    
Usage: 
    kioskparam [-xkSq][-e <envvar>,...][-E <prefix>] [-u <user>]   [<pattern> ...]
    kioskparam [-xkSq][-e <envvar>,...][-E <prefix>]  -d <display> [<pattern> ...]
    kioskparam [-xkSq][-e <envvar>,...][-E <prefix>]  -s <display> [<pattern> ...]
    kioskparam [-xkSq][-e <envvar>,...][-E <prefix>]  -f <file>    [<pattern> ...]
    kioskparam -h
!
}

usage()
{
 show_usage   
 exit ${1:-1}
}

help()
{
# TODO implement command-specific help  
  show_usage  
  cat 1>&2 <<!    
 
Options:
  -u <user>          Show parameters for the session currently running under
                     the specified kiosk user account. Default is the current
                     session.
  -d <display>       Show parameters for the session currently running on the
                     specified display. 
  -s <display>       Show parameters statically configured for the next session
                     to run on the specified display.
  -f <file>          Show parameters for the specified session.conf(@(FRMT)) 
                     file.
  -k                 Print only the value for the selected key(s). The default 
                     is to print <key>=<value> pairs.
  -x                 Escape/quote the key=value output, so it can safely be 
                     evaluated as shell assignments.
  -e <env>           Expand the environment variable <env>, as if it were part 
                     of the session configuration.
                     This option may be provided multiple times.
  -E <prefix>        Expand environment variables starting with <prefix>, if 
                     referenced as part of the configuration.
                     This option may be provided only once.
		     The default for this options is "KIOSK_".
  -S                 Expand a standard set of environment variables, as used 
                     by the kiosk framework itself. Also sets these based on 
		     provided parameters for an active session.
		     This option implies -e USER -e HOME -e DISPLAY.
  -q                 Quiet mode (no errors or warning printed)
  -X <readcfg>       Special private option used for testing and debugging.
  -h                 Print a short usage message.
!

 exit 0
}

#
## getActiveKioskUserForDisplay
#
## getActiveKioskDisplayForUser
#
# These routines map between username and (normalized) display name
# for identifying kiosk users. Both routines can also be used to check 
# if the passed in username or display identifier is a valid identifier 
# for an active kiosk session.
#
# Note: The kiosk sessios validity check is not as thorough as the checks
#       done in  kioskstatus(1). Additionally these routines and their use
#       have some intrinsic race conditions, as we don't acquire a kiosk user
#       lock, but that applies even more to creation/removal of
#       the active session config file (for which there is no lock).
#       We'll probably fall over later (and can't do real damage)
#       in such cases. Under certain circumstances we may report settings
#       of 'zombie' sessions.
# 
getActiveKioskDisplayForUser() 
{
        _user="$1"
        cat $KIOSK_DYN_DIR/users/$_user.session 2>/dev/null
}

getActiveKioskUserForDisplay() 
{
        _display="$1"
        cat $KIOSK_DYN_DIR/users/$_display.dpy 2>/dev/null
}

#
## countWords - argument validation helper
#
## counts the number of shell words in the passed arguments
#
countWords()
{
  echo $#
}

HAVE_UTILS=false
#
## helpers for utils.sh functions, which might be absent in
## debug mode
#
getSessionDescriptorFile()
{
  sessNam="$1"
  sessDir="/etc/opt/SUNWkio/sessions"
  if $HAVE_UTILS ; then
   sessionNameToDescriptorFile "$sessNam"
  else
   # Simplified implementation
   # This is currently only used in debug/unit test mode (-X)
   if [ -s "./$sessNam" ] ; then
    printf "./%s" "$sessNam"
   elif [ -s "$sessDir/$sessName.conf" ] ; then
    printf "$sessDir/%s.conf" "$sessNam"
   else
    printf "%s" "$sessNam"
   fi
  fi
}

#
## main
#

#
## parse args
#
READCFG="readcfg"

# default to selecting the current session (by user name)
theConfigSelection="u"
theConfigSelector="$USER"

envopts=""
envprefix="KIOSK_"
stdenv=false
stripopts="-x" # Always perform legacy quote stripping
outopts=""
quiet=false
debug=false
while getopts "xkSqd:f:s:u:e:E:X:h" theOption ; do
 case $theOption in
  d|f|s|u) 
   theConfigSelection=$theOption
   theConfigSelector="$OPTARG"
   ;;

  e)
   _envarg="$OPTARG"
   if [ `countWords $_envarg` -ne 1 ] ; then
    printf 1>&2 "Error: invalid environment variable name: '%s'\n" "$_envarg"
    exit 1
   fi
   envopts="$envopts -e $_envarg"
   ;;

  E)
   _envarg="$OPTARG"
   if [ `countWords $_envarg` -ne 1 ] ; then
    printf 1>&2 "Error: invalid environment variable prefix: '%s'\n" "$_envarg"
    exit 1
   fi
   envprefix="$_envarg"
   ;;

  S)
   stdenv=true
   ;;

  k)
   outopts="$outopts -k"
   ;;

  x)
   outopts="$outopts -s"
   ;;

  X)
   debug=true
   READCFG="$OPTARG"
   ;;

  q)
   quiet=true
   ;;

  h)
   help
   ;;

  \?)
   usage
   ;;
 esac
done

shift `expr $OPTIND - 1 ` 

#
## Load utilities and setup basic Kiosk Environment
#
theUtilsFile=/opt/SUNWkio/lib/utils.sh
if $debug ; then
 # Debug requires file mode
 if [ "$theConfigSelection" != "f" ] ; then
  $quiet || printf 1>&2 "Error: test/debug mode requires the -f option\n"
  exit 1
 fi
elif [ ! -r $theUtilsFile ] ; then
 $quiet || printf 1>&2 "Error: can't read Kiosk utils file '%s'\n" "$theUtilsFile"
 exit 1
else
 . $theUtilsFile
 if [ $? -ne 0 ] ; then
  $quiet || printf 1>&2 "Error: failed to load Kiosk utils file '%s'\n" "$theUtilsFile"
  exit 1
 fi
 READCFG="$KIOSK_LIB_DIR/readcfg"
 HAVE_UTILS=true
fi

# Now evaluate the selection
fileselect=""
theUser=""
theDisplay=""
case $theConfigSelection in
 u)
  # theConfigSelector is the user name
  theUser="$theConfigSelector"
  theDisplay=`getActiveKioskDisplayForUser "$theUser"`
  if [ $? -ne 0 ] || [ -z "$theDisplay" ] ; then
   $quiet || printf 1>&2 "Warning: No kiosk session found for user '$theUser'\n"
  fi
  fileselect="$KIOSK_DYN_DIR/sessions/$theUser/session.conf"
  ;;
 d)
  # theConfigSelector is the display
  # need to map to user
  theDisplay=`normalizeDisplay "$theConfigSelector"`
  if [ $? -ne 0 ] || [ -z "$theDisplay" ] ; then
   $quiet || printf 1>&2 "Error: Invalid display name '%s'\n" "$theConfigSelector"
   exit 1
  fi
  theUser=`getActiveKioskUserForDisplay "$theDisplay"`
  if [ $? -ne 0 ] || [ -z "$theUser" ] ; then
   $quiet || printf 1>&2 "Error: No kiosk session found for display '%s'\n" "$theDisplay"
   exit 1
  fi
  fileselect="$KIOSK_DYN_DIR/sessions/$theUser/session.conf"
  ;;
 s)
  # theConfigSelector is the display
  # configured statically
  theDisplay=`normalizeDisplay "$theConfigSelector"`
  if [ $? -ne 0 ] || [ -z "$theDisplay" ] ; then
   $quiet || printf 1>&2 "Error: Invalid display name '%s'\n" "$theConfigSelector"
   exit 1
  fi
  fileselect="$KIOSK_VAR_DIR/config/$theDisplay"
  ;;
 f)
  fileselect="$theConfigSelector"
  ;;
# *) This can't happen
esac

if [ -z "$fileselect" ] || [ ! -s "$fileselect" ] ; then
  $quiet || printf 1>&2 "Error: session.conf file '%s' not found!\n" "$fileselect"
  exit 1
fi

# Setup standard environment 
if $stdenv ; then
  # Infer environment values from session properties
  if [ -n "$theDisplay" ] ; then
    DISPLAY="$theDisplay"
    export DISPLAY
  fi
  if [ -n "$theUser" ] ; then
    USER="$theUser"
    export USER

    HOME="${KIOSK_VAR_DIR:-/var/opt/SUNWkio}/home/$theUser"
    export HOME 
  fi

  # Add environment options, if setting available
  if [ -n "$DISPLAY" ] ; then
    envopts="-e DISPLAY $env_opts"
  fi
  if [ -n "$USER" ] ; then
    envopts="-e USER $env_opts"
  fi
  if [ -n "$HOME" ] ; then
    envopts="-e HOME $env_opts"
  fi
fi

#
## Set up supported environment variables for use in config resolution
## (This will only work, if envprefix is or subsumes "KIOSK_")
#
[ -z "${KIOSK_CONFIG_DIR:-}" ]    || export KIOSK_CONFIG_DIR
[ -z "${KIOSK_SESSIONS_DIR:-}" ]  || export KIOSK_SESSIONS_DIR
[ -z "${KIOSK_APPS_DIR:-}" ]      || export KIOSK_APPS_DIR
[ -z "${KIOSK_PROTOS_DIR:-}" ]    || export KIOSK_PROTOS_DIR
[ -z "${KIOSK_TEXTDOMAIN:-}" ]    || export KIOSK_TEXTDOMAIN
[ -z "${KIOSK_TEXTDOMAINDIR:-}" ] || export KIOSK_TEXTDOMAINDIR

if [ -n "$envprefix" ] ; then
  envopts="-E $envprefix $env_opts"
fi

# 0. Don't do KIOSK_ENABLED Check (might add an option to print it always)

# If we can't find a descriptor, just read the session.conf file
kioskSessionDesc="/dev/null"

# 1. Get KIOSK_SESSION value
kioskSession=`"$READCFG" -xk -f "$fileselect" KIOSK_SESSION`
if [ -n "$kioskSession" ] ; then
  # 2. Get the session descriptor file
  theSessionDesc=`getSessionDescriptorFile "$kioskSession"`
  if [ -s "$theSessionDesc" ] ; then
   kioskSessionDesc="$theSessionDesc"
  else
   $quiet || printf "Warning: Kiosk Session Descriptor '%s' not found\n" "$kioskSessionDesc >&2"
  fi
else
 $quiet || printf "Warning: \$KIOSK_SESSION not specified in '%s'\n" "$fileselect" >&2
fi

# 3. Set up KIOSK_SESSION_DIR
#    - Use environment, so that value from descriptor takes precedence
if [ -z "$KIOSK_SESSION_DIR" ] ; then
  descbase=`printf "%s\n" "$kioskSessionDesc" | /bin/sed 's/\.[A-Za-z]*$//'`
  if [ "$kioskSessionDesc" != "$descbase" ] ; then
    KIOSK_SESSION_DIR="$descbase"
    export KIOSK_SESSION_DIR
  fi
fi  

# 4. Read the descriptor and session files
#    Read the descriptor file first, so that the
#    session configuration can override it
if $quiet ; then
  err_redirect="2>/dev/null"
else
  err_redirect=""
fi
cat "$kioskSessionDesc" "$fileselect" | 
    "$READCFG" $stripopts $outopts $envopts "$@" $err_redirect
