#!/bin/ksh
#
#*******************************************************************************
#
# ident "@(#)utcammigrate.ksh	1.9 10/04/14 SMI"
#
# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#*******************************************************************************
#

#
# Solaris 10 Trusted Extension guard
#
ORIGIN=`/usr/bin/dirname $0`
UTIL_LIB=${ORIGIN:-/opt/SUNWut/lib}/../lib/support_lib/util_lib
. $UTIL_LIB
FailExecInLocalZoneOnTx 
#
# Solaris 10 Trusted Extension guard 

# CR 6551572 workaround: Apollo uses the wrong setting
#KIOSK_SUNRAY_TIMEOUT_SETTING="KIOSK_SUNRAY_SESSION_DISCONNECT_TIMEOUT
KIOSK_SUNRAY_TIMEOUT_SETTING="KIOSK_SESSION_TIMEOUT_DETACHED"

#
## Add a file/directory name to the list of files to be tarred removing
## $theConfigDir first.
#
addToTarFlist()
{
 typeset theFile=${1#$theConfigDir\/}
 theTarFlist="$theTarFlist $theFile"
}

#
## Create an application descriptor for a given CAM application
#
createAppDescriptor()
{
 typeset inPath=$1
 typeset inProtoName=$2
 typeset inIndex=$3

 #
 ## The CAM appPath may include application arguments. These should not be
 ## included in KIOSK_APP_EXEC ( although it might be useful to provide them
 ## as KIOSK_APP_ARGS ). They are included as application arguments in the
 ## application list.
 #
 typeset theAppExec=${appPath[inIndex]%%[   ]*}
 typeset theContents="#\n##Migrated CAM application\n#\n\
  KIOSK_APP_EXEC=\"$theAppExec\"\n
  KIOSK_APP_LABEL=\"${appLabel[inIndex]}\"\n
  KIOSK_APP_DESCRIPTION=\"Migrated CAM application '${appName[inIndex]}'\"\n"
 if [ -n "$inProtoName" ] ; then
  theContents="$theContents KIOSK_APP_PROTOTYPE=\"$inProtoName\"\n"
 fi
 echo $theContents > "$inPath" && chmod a+r "$inPath"
 if [ $? -ne 0 ] ; then
  print -u2 "Error: failed to write Kiosk application descriptor '$inPath'"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Upload the resulting session configuration and application list to the
## Sun Ray administration database.
#
doUpload()
{
 echo "Uploading migration result to Sun Ray administration database ..."
 typeset theArgs="-i session -f $theSessionFile"
 if [ -f $theAppListFile ] ; then
  theArgs="$theArgs -A $theAppListFile"
 fi
 $theUTSbin/utkiosk $theArgs 
 if [ $? -ne 0 ] ; then
  print -u2 "Error: failed to import session configuration"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Copy a CAM prototype to the prototypes subdirectory of our target,
## possibly renaming it at the same time.
#
createAppPrototype()
{
 typeset inPath=$1
 typeset inIndex=$2

 mkdir -p "$inPath" && chmod 755 "$inPath" &&
 ( cd "$camProtoDir/${appName[inIndex]}" && tar cf - . | 
   ( cd "$inPath" && tar xf - ) )
 if [ $? -ne 0 ] ; then
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## download and source the old CAM configuration
#
loadCamConfig()
{
 typeset theTmpFile=/tmp/utcammigrate.$$
 $theUTSbin/utkiosk -e kiosk > $theTmpFile &&
 . $theTmpFile
 theRC=$?
 rm -f $theTmpFile
 if [ $theRC != 0 ] ; then
  print -u2 "Error: failed to load CAM configuration"
  return $KIOSK_RESULT_FAILED
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Create an application list entry for a previousl enabled CAM application.
#
makeAppListEntry()
{
 typeset inName=$1
 typeset inIndex=$2

 if [ "${appEnable[inIndex]}" != $camEnabled ] ; then
  return $KIOSK_RESULT_SUCCESS
 fi

 case "${appAttribute[inIndex]}" in
  $camCritical)
   typeset theMode=$kioskCritical;;
  $camMenu)
   typeset theMode=$kioskUser;;
  $camAuto)
   typeset theMode=$kioskAuto;;
  *)
   print -u2 "Error: invalid CAM application attribute '$inMode' for application '$inName'"
   return $KIOSK_RESULT_FAILED;;
 esac

 #
 ## The CAM appPath may include application arguments. Strip these out and
 ## include them in the application list entry.
 #
 typeset theArgs=${appPath[inIndex]#*[  ]*}
 if [ "$theArgs" = "${appPath[inIndex]%%[   ]*}" ] ; then
  unset theArgs
 fi

 echo "$kioskDesc:$inName:$theMode;$theArgs"
 return $KIOSK_RESULT_SUCCESS
}

#
## The following two functions are used to detect existing descriptors and
## prototypes which shouldn't be overwritten and to generate alternative names
## for same in these cases.
#
makeKioskAppName()
{
 if [ -f "$theAppsDir/$1.conf" ] ; then
  echo migrated.$1
 else
  echo $1
 fi
}
makeKioskProtoName()
{
 if [ -d "$camProtoDir/$1" ] ; then
  if [ -d "$theProtosDir/$1" ] ; then
   echo migrated.$1
  else
   echo $1
  fi  
 fi
}

#
## Create the output tar file
#
makeTar()
{
 if [ -n "$theTarFlist" ] ; then
  echo "Creating results tarfile '$theTarFile' ..."
  ( cd "$theConfigDir" && tar cf "$theTarFile" `echo $theTarFlist` )
  if [ $? -ne 0 ] ; then
   return $KIOSK_RESULT_FAILED
  fi
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Migrate an individual CAM application. This includes:
## 1. Creating an application descriptor and storing its name in $theTarFlist
##    for use when creating the results tarfile.
## 2. Creating a prototype and storing its name in $theTarFlist for use when
##    when creating the results tarfile.
## 3. Creating an application list entry and storing it in $theAppList for use
##    when creating the applicatio list file.
#
migrateApp()
{
 typeset inIndex=$1

 if [    -z "${appName[inIndex]}"      \
      -o -z "${appPath[inIndex]}"      \
      -o -z "${appAttribute[inIndex]}" \
      -o -z "${appEnable[inIndex]}" ] ; then
  print -u2 "Error: invalid application found in the Sun Ray administration database"
  print -u2 "       application name: '${appName[inIndex]}'"
  print -u2 "       application path: '${appPath[inIndex]}'"
  print -u2 "       application attribute: '${appAttribute[inIndex]}'"
  print -u2 "       application enabled: '${appEnable[inIndex]}'"
  return $KIOSK_RESULT_FAILED
 fi
 echo "Migrating application '${appName[inIndex]}' ..."
 typeset theAppName=`makeKioskAppName ${appName[inIndex]}`
 typeset theProtoName=`makeKioskProtoName ${appName[inIndex]}`

 createAppDescriptor "$theAppsDir/$theAppName.conf" "$theProtoName" $inIndex
 if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
  return $KIOSK_RESULT_FAILED
 fi
 addToTarFlist "$theAppsDir/$theAppName.conf"

 if [ -n "$theProtoName" ] ; then
  createAppPrototype "$theProtosDir/$theProtoName" $inIndex
  if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
   return $KIOSK_RESULT_FAILED
  fi
  addToTarFlist "$theProtosDir/$theProtoName"
 fi

 typeset theEntry=`makeAppListEntry "$theAppName" $inIndex`
 if [ $? -eq $KIOSK_RESULT_FAILED ] ; then 
  return $KIOSK_RESULT_FAILED
 fi
 if [ -n "$theEntry" ] ; then
   theAppList="$theAppList\n$theEntry"
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Create an application list including all enabled CAM applications.
## If successful, we add the application list file to theTarFlist so that it's
## included in our output tar file.
#
migrateAppList()
{
 rm -f $theAppListFile
 if [ $? -ne 0 ] ; then
  print -u2 "Error: failed to remove old application list file '$theAppListFile'"
  return $KIOSK_RESULT_FAILED
 fi
 if [ -n "$theAppList" ] ; then
  echo $theAppList > $theAppListFile
  if [ $? -ne 0 ] ; then
   print -u2 "Error: failed to create application list file '$theAppListFile'"
   return $KIOSK_RESULT_FAILED
  fi
  addToTarFlist "$theAppListFile"
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Iterate over available CAM applications migrating them one by one.
#
migrateApps()
{
 echo "Migrating applications ..."
 if [ -n "$numApps" ] ; then
  typeset haveError=0
  typeset theIndex=0
  while [ $theIndex -lt "$numApps" ] ; do
  #
  ## Switch off no-dtsession mode if CAM includes an enabled dtsession app.
  #
   if [ -n "${appName[theIndex]}" -a "${appName[theIndex]}" = "dtsession" ]
   then
    if [ "${appEnable[theIndex]}" = $camEnabled ] ; then
     theSessionArgs=""
    fi
   else
    migrateApp $theIndex
    if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
     haveError=1
    fi
   fi
   theIndex=`expr $theIndex + 1`
  done
  if [ $haveError -eq 1 ] ; then
   return $KIOSK_RESULT_FAILED
  fi
 fi
 return $KIOSK_RESULT_SUCCESS
}

#
## Create the session configuration
#
migrateSessionConfig()
{
 echo "Migrating session configuration ..."
 typeset theContents="#\n##Migrated CAM session configuration\n#\nKIOSK_SESSION=cde\n"
 if [ -n "$theSessionArgs" ] ; then
  theContents="${theContents}KIOSK_SESSION_ARGS=\"$theSessionArgs\"\n"
 fi
 if [ -n "$action" -a "$action" -eq 1 -a -n "$timeout" ] ; then
  theContents="${theContents}${KIOSK_SUNRAY_TIMEOUT_SETTING}=$timeout\n"
 fi
 if [ -n "$maxVM" -a "$maxVM" != "unlimited" ] ; then
  theContents="${theContents}KIOSK_SESSION_LIMIT_VMSIZE=$maxVM\n"
 fi
 if [ -n "$maxFile" -a "$maxFile" != "unlimited" ] ; then
  theContents="${theContents}KIOSK_SESSION_LIMIT_FILESIZE=$maxFile\n"
 fi
 if [ -n "$maxCPU" -a "$maxCPU" != "unlimited" ] ; then
  theContents="${theContents}KIOSK_SESSION_LIMIT_CPU=$maxCPU\n"
 fi
 echo $theContents > "$theSessionFile"
 if [ $? -ne 0 ] ; then
  return $KIOSK_RESULT_FAILED
 fi
 addToTarFlist "$theSessionFile"
 return $KIOSK_RESULT_SUCCESS
}

#
## Remove created files & directories in the event of a migration error
#
rollback()
{
 echo "A migration error occurred. All changes will now be undone."
 ( cd "$theConfigDir" && rm -rf $theTarFile $theTarFlist )
}

usage()
{
 echo "Usage:"
 echo "      utcammigrate [-u] [-t] [-d directory]"
 echo "      utcammigrate -h"
 echo ""
 echo "      -u             automatically upload any generated Kiosk session"
 echo "                     configuration and application list to the Sun Ray"
 echo "                     administration database."
 echo "      -t             create a tar archive,"
 echo "                     /etc/opt/SUNWkio/cam-migrated.tar containing the"
 echo "                     results of the migration."
 echo "      -d directory   use the specified directory instead of"
 echo "                     /etc/opt/SUNWkio for all created files."
 echo "      -h             print a usage message and exit."
}

#
## Main
#
theKioskLib=/opt/SUNWkio/lib
theUTSbin=/opt/SUNWut/sbin

#
## Load utilities and setup basic Kiosk Environment
#
theUtilsFile=$theKioskLib/utils.sh
if [ ! -r $theUtilsFile ] ; then
 print -u2 "Error: can't read Kiosk utils file '$theUtilsFile'"
 exit 1
else
 . $theUtilsFile
 if [ $? -ne 0 ] ; then
 print -u2 "Error: failed to load Kiosk utils file '$theUtilsFile'"
 exit 1
 fi
fi

#
## Process command line parameters
#
theConfigDir=$KIOSK_CONFIG_DIR
doUpload=0
doTar=0
while getopts uthd: inOpt ; do
 case $inOpt in
  u)  doUpload=1;;
  t)  doTar=1;;
  d)  theConfigDir="$OPTARG";;
  h)  usage
      exit 0;;
  \?) print -u2 "Error: invalid parameter specified"
      usage
      exit 1;;
 esac
done

#
## Download and source the old CAM configuration
#
loadCamConfig
if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
 exit 1
fi

theAppsDir="$theConfigDir/applications"
theProtosDir="$theConfigDir/prototypes"
mkdir -p "$theAppsDir" "$theProtosDir"
if [ $? -ne 0 ] ; then
 print -u2 "Error: failed to create application and/or prototype directories,"
 print -u2 "       '$theAppsDir' and '$theProtosDir'"
 exit 1
fi

theSessionFile="$theConfigDir/cam-session.conf"
theAppListFile="$theAppsDir/cam-applications.list"
theTarFile="cam-migrated.tar"
#
## theTarFlist is used to hold a list of files & directories which should be
## added to the tarfile created when the -t option is specified.
#
theTarFlist=""
theAppList=""

#
## theSessionArgs will eventutally be used to set the value of
## KIOSK_SESSION_ARGS. If the dtsession application is found in the list of
## enabled CAM applications theSessionArgs will be blanked out i.e. 
## no-dtsession mode will be switched off.
#
theSessionArgs="-no-dtsession"

#
## Some strings used by old CAM
#
camProtoDir=/var/opt/SUNWut/kiosk/prototypes
camEnabled="1"
camCritical="0"
camMenu="1"
camAuto="2"

#
## Some strings used by Kiosk ( in application lists )
#
kioskDesc="desc"
kioskCritical="critical"
kioskUser="user"
kioskAuto="auto"

migrateApps
if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
 rollback
 exit 1
fi

migrateAppList
if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
 rollback
 exit 1
fi

migrateSessionConfig
if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
 rollback
 exit 1
fi

if [ $doTar -eq 1 ] ; then
 makeTar
 if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
  exit 1
 fi
fi

if [ $doUpload -eq 1 ] ; then
 doUpload
 if [ $? -eq $KIOSK_RESULT_FAILED ] ; then
  exit 1
 fi
fi

exit 0
