#!/usr/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2006,2007 Bernd Schemmer  All rights reserved.
# Use is subject to license terms.

# Notes:
#
# - use "xen_explorer.sh {-v} -h" to get the usage help
# - the main code starts after the line containing "main:"
#
# - use "xen_explorer.sh -H 2 >xen_explorer.sh.doc" to get the documentation
#
# - this is a Kornshell script - it may not function correctly in other shells
##
# -----------------------------------------------------------------------------
##
## xen_explorer.sh - collect information about the installed Xen environment
##
## Author: Bernd Schemmer (Bernd.Schemmer@gmx.de)
##
## Version: see variable ${__SCRIPT_VERSION} below
##          (see variable ${__SCRIPT_TEMPLATE_VERSION} for the template
##           version used)
##
## Supported OS: Solaris 10 and newer
##
##
## Description
##
## This script collects information about an installed Xen environment
## This script supports Xen for Solaris 07/07; the script should run in the Dom0
##
## Configuration file
##
## This script supports a configuration file called <scriptname>.conf.
## The configuration file is searched in the working directory,
## the home directory of the user executing this script and /etc
## (in this order).
##
## The configuration file is read before the parameter are read.
##
## See the variable __CONFIG_PARAMETER below for the possible entries in
## the config file.
##
## Predefined parameter
##
## see the subroutines ShowShortUsage and ShowUsage
##
##
## History:
##   15.l1.2006 v0.0.1 /bs
##     initial release
##
##   31.07.2007 v.0.0.2 /bs
##     changed the script for Xen 07/07
##
##   ??.??.2007 v0.0.3 /bs 
##     version missing ...
##
##   11.02.2008 v0.0.4 /bs
##     added output of syseventadm list
##     added code for Solaris snv_78 and newer
##
## script template History
## -----------------------
##   1.22.0 08.06.2006 /bs
##     public release; starting history for the script template
##
##   1.22.1 12.06.2006 /bs
##      added true/false to CheckYNParameter and ConverToYesNo
##
##   1.22.2. 21.06.2006 /bs
##      added the parameter -V
##      added the use of environemnt variables
##      added the variable __NO_TIME_STAMPS
##      added the variable __NO_HEADERS
##      corrected a bug in the function executeCommandAndLogSTDERR
##      added missing return commands
##
##   1.22.3 24.06.2006 /bs
##      added the function StartStop_LogAll_to_logfile
##      added the variable __USE_TTY (used in AskUser)
##      corrected an spelling error (dev/nul instead of /dev/null)
##
##   1.22.4 06.07.2006 /bs
##      corrected a bug in the parameter error handling routine
##
##   1.22.5 27.07.2006 /bs
##      corrected some minor bugs
##
##   1.22.6 09.08.2006 /bs
##      corrected some minor bugs
##
##   1.22.7 17.08.2006 /bs
##      add the CheckParameterCount function
##      added the parameter -T
##      added long parameter support (e.g --help)
##
##   1.22.8 07.09.2006 /bs
##      added code to save the env variable LANG and set it temporary to C
##
##   1.22.9 20.09.2006 /bs
##      corrected code to save the env variable LANG and set it temporary to C
##  
##   1.22.10 21.09.2006 /bs
##      cleanup comments
##      the number of temporary files created automatically is now variable
##        (see the variable __NO_OF_TEMPFILES)
##      added code to install the trap handler in all functions
##
##   1.22.11 19.10.2006 /bs
##      corrected a minor bug in AskUser (/c was not interpreted by echo)
##      corrected a bug in the handling of the parameter -S (-S was ignored)
##
##   1.22.12 31.10.2006 /bs
##      added the variable __REQUIRED_ZONE
##
##   1.22.13 13.11.2006 /bs
##      the template now uses TMP or TEMP if set for the temporary files
##
##   1.22.14 14.11.2006 /bs
##      corrected a bug in the function AskUser (the default was y not n)
##
##   1.22.15 21.11.2006 /bs
##      added initial support for other Operating Systems
##
##   1.22.16 05.07.2007 /bs
##      enhanced initial support for other Operating Systems
##      Support for other OS is still not fully tested!
##
##   1.22.17 06.07.2007 /bs
##      added the global variable __TRAP_SIGNAL
##
## ----------------
## Version variables
##
## __SCRIPT_VERSION - the version of your script
##
typeset -r __SCRIPT_VERSION="v0.0.4"
##

## __SCRIPT_TEMPLATE_VERSION - version of the script template
##
typeset -r __SCRIPT_TEMPLATE_VERSION="1.22.17 06.07.2007"
##

## ----------------
##
## Predefined return codes:
##
##    1 - show usage and exit
##    2 - invalid parameter found
##
##  210 - 237 reserved for the runtime system
##  238 - unsupported Operating system
##  239 - script runs in a not supported zone
##  240 - internal error
##  241 - a command ended with an error (set -e is necessary to activate this trap)
##  242 - the current user is not allowed to execute this script
##  243 - invalid machine architecture
##  244 - invalid processor type
##  245 - invalid machine platform
##  246 - error writing the config file
##  247 - include script not found
##  248 - unsupported OS version
##  249 - Script not executed by root
##  250 - Script is already running
##
##  251 - QUIT signal received
##  252 - User break
##  253 - TERM signal received
##  254 - unknown external signal received
##
##
## ----------------
## Used environment variables
##
#
# The variable __USED_ENVIRONMENT_VARIABLES is used in the function ShowUsage
#
__USED_ENVIRONMENT_VARIABLES="
## __DEBUG_CODE
## __RT_VERBOSE_LEVEL
## __QUIET_MODE
## __VERBOSE_MODE
## __VERBOSE_LEVEL
## __OVERWRITE_MODE
## __USER_BREAK_ALLOWED
## __NO_TIME_STAMPS
## __NO_HEADERS
## __USE_COLORS
## __USE_RBAC
## __TEE_OUTPUT_FILE
"

#
# binaries and scripts used in this script:
#
# basename cat cp cpio cut dd dirname expr find grep id ln ls prtdiag pwd rebboot rm sed tee touch tty umount uname who zonename
#
# /usr/bin/pfexec
# /usr/ucb/whoami or $( whence whoami )
# /usr/openwin/bin/resize or $( whence resize )
#

# -----------------------------------------------------------------------------

# variables for the trap handler

__FUNCTION="main"


# alias to install the trap handler
#
alias __settrap='
  trap "GENERAL_SIGNAL_HANDLER  1    \$LINENO"  1
  trap "GENERAL_SIGNAL_HANDLER  2    \$LINENO"  2
  trap "GENERAL_SIGNAL_HANDLER  3    \$LINENO"  3
  trap "GENERAL_SIGNAL_HANDLER 15    \$LINENO" 15
#  trap "GENERAL_SIGNAL_HANDLER exit  \$LINENO" EXIT
'

##
## ----------------
## ##### general hints
##
## Do not use variable names beginning with __ (these are reserved for
## internal use)
##


# save the language setting and switch the language temporary to C
#
__SAVE_LANG="${LANG}"
LANG=C
export LANG

# -----------------------------------------------------------------------------
## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1


## ----------------
## internal variables
##
## __TRAP_SIGNAL - current trap catched by the trap handler
##   This is a global variable that can be used in the exit routines
##
__TRAP_SIGNAL=""


# -----------------------------------------------------------------------------
## __USE_RBAC - set this variable to ${__TRUE} to execute this script
##   with RBAC
##   default is ${__FALSE}
##
typeset  __USE_RBAC=${__USE_RBAC:=${__FALSE}}

# -----------------------------------------------------------------------------
# use the parameter --tee to automatically call the script and pipe
# all output to tee
#
__TEE_OUTPUT_FILE="${__TEE_OUTPUT_FILE:=/var/tmp/$( basename $0 ).tee.log}"

if [ "$1"x = "-T"x -o "$1"x = "--tee"x ] ; then
# Note: If you need the parent PID save it here
#
   __PPID=$PPID ; export __PPID

  echo "Saving STDOUT and STDERR to \"${__TEE_OUTPUT_FILE}\" ..."
  shift
  exec $0 $@ 2>&1 | tee -a "${__TEE_OUTPUT_FILE}"
  exit $?
fi

[ "${__PPID}"x = ""x ] && __PPID=$PPID ; export __PPID

# -----------------------------------------------------------------------------
#
# Set the variable ${__USE_RBAC} to ${__TRUE} to activate RBAC support
#
# Allow the use of RBAC to control who can access this script. Useful for
# administrators without root permissions
#
if [ "${__USE_RBAC}" = "${__TRUE}" ] ; then
  if [ "$_" != "/usr/bin/pfexec" -a -x /usr/bin/pfexec ]; then
    /usr/bin/pfexec $0 $*
    exit $?
  else
    echo "${0%%*/} ERROR: /usr/bin/pfexec not found or not executable!" >&2
    exit 238
  fi
fi

# -----------------------------------------------------------------------------
##
## ##### defined variables that may be changed
##


## __DEBUG_CODE - code executed at start of every sub routine
##   Note: Use always "__DEBUG_CODE="eval ..." if you want to use variables or aliase
##         Default debug code : none
##
  __DEBUG_CODE=""

# __FUNCTION_INIT - code executed at start of every sub routine
#   (see the hints for __DEBUG_CODE)
#         Default init code : install the trap handlers
  __FUNCTION_INIT="eval __settrap"


##
## sample debug code:
## __DEBUG_CODE="  eval echo Entering the subroutine \$__FUNCTION ...  "
##
## Note: Use an include script for more complicate debug code, e.g.
## __DEBUG_CODE=" eval . /var/tmp/mydebugcode"
##

## unique string
##
UNIQUE_STRING="$( uname -n).$( date +%y%m%d_%H%M%S )"

## __CONFIG_PARAMETER
##   The variable __CONFIG_PARAMETER contains the configuraton variables
##
## The defaults for these variables are defined here. You
## can use a config file to overwrite the defaults.
##
## Use the parameter -C to create a default configuration file
##
## Note: The config file is read and interpreted via ". configfile" 
##       therefor you can add also some code her
##
__CONFIG_PARAMETER='

# extension for backup files
#
  DEFAULT_BACKUP_EXTENSION=".$$.backup"

# output file
# (use the parameter -o to change this variable)
#
  DEFAULT_OUTPUT_FILE="/var/tmp/xen_explorer_${UNIQUE_STRING}.html"

# default no of lines to print for logfiles
#
  DEFAULT_LOGFILE_LINE_COUNT=50

# default system message file

  DEFAULT_SYSTEM_MESSAGE_FILE="/var/adm/messages"
  DEFAULT_SYSTEM_LOG_FILE="/var/log/syslog"
  
# only change the following variables if you know what you are doing 
#

# array for additional commands to execute
#
  COMMAND_ARRAY[0]=0

# list of xen config files
#
  XEN_CONFIG_FILE_ARRAY[0]=0
   
# no further internal variables defined yet
#
# Note you can redefine any variable that is initialized before calling
# ReadConfigFile here!
'
# end of config parameters


## __SHORT_DESC - short description (for help texts, etc)
##   Change to your need
##
typeset -r __SHORT_DESC="collect information about the Xen environment"

## __LONG_USAGE_HELP - Additional help if the script is called with
##   the parameter "-v -h"
##
##   Note: To use variables in the help text use the variable name without
##         an escape character, eg. ${OS_VERSION}
##
__LONG_USAGE_HELP='
      -c command
         add the output of the command \"command\" to the results,
	    this parameter can be used more than once
         Long format: --command

      -i configfile
         other config files to include in the output
	    this parameter can be used more than once
         Long format: --other_configfile
	
      -o output-file
         change the name of the output file
	 current value: \"${OUTPUT_FILE}\"
         Long format: --output_file

      -N no of lines to read from the logfiles
         current value: ${LOGFILE_LINE_COUNT}
         Long format: --logfile_linecount
'

## __SHORT_USAGE_HELP - Additional help if the script is called with the parameter "-h"
##
##   Note: To use variables in the help text use the variable name without an escape
##         character, eg. ${OS_VERSION}
##
__SHORT_USAGE_HELP='                         [-c command] [-i configfile] [-o outputfile-name] [-N n]
'


## __MUST_BE_ROOT - run script only by root (def.: false)
##   set to ${__TRUE} for scripts that must be executed by root only
##
__MUST_BE_ROOT=${__TRUE}

## __REQUIRED_USERID - required userid to run this script (def.: none)
##   use blanks to separate multiple userids
##   e.g. "oracle dba sysdba"
##   "" = no special userid required
##
__REQUIRED_USERID=""

## __REQUIRED_ZONE - required zone (either global, non-global or local or the name of a zone)
##   (def.: none)
##   "" = no special zone required
##
__REQUIRED_ZONE=""

## __ONLY_ONCE - run script only once at a time (def.: false)
##   set to ${__TRUE} for scripts that can not run more than one instance at
##   the same time
##
__ONLY_ONCE=${__FALSE}

## __ REQUIRED_OS - required OS (uname -s) for the script (def.: none)
##    use blanks to separate the OS names if the script runs under multiple OS
##    e.g. "SunOS"
##
__REQUIRED_OS="SunOS"


## __REQUIRED_OS_VERSION - required OS version for the script (def.: none)
##   minimum OS version necessary, e.g. 5.10
##   "" = no special version necessary
##
__REQUIRED_OS_VERSION="5.11"

## __REQUIRED_MACHINE_PLATFORM - required machine platform for the script (def.: none)
##   required machine platform (uname -i) , e.g "i86pc"; use blanks to separate
##   the multiple machine types, e.g "Sun Fire 3800 i86pc"
##   "" = no special machine type necessary
##
__REQUIRED_MACHINE_PLATFORM=""

## __REQUIRED_MACHINE_CLASS - required machine class for the script (def.: none)
##   required machine class (uname -m) , e.g "i86pc" ; use blanks to separate 
##   the multiple machine classes, e.g "sun4u i86pc"
##   "" = no special machine class necessary
##
__REQUIRED_MACHINE_CLASS=""

## __REQUIRED_MACHINE_ARC - required machine architecture for the script (def.: none)
##   required machine architecture (uname -p) , e.g "i386" ; use blanks to separate
##   the machine architectures if more than one entry, e.g "sparc i386"
##   "" = no special machine architecture necessary
##
__REQUIRED_MACHINE_ARC=""

## __VERBOSE_LEVEL - count of -v parameter (def.: 0)
##
typeset -i __VERBOSE_LEVEL=${__VERBOSE_LEVEL:=0}

## __RT_VERBOSE_LEVEL - level of -v for runtime messages (def.: 1)
##
##   e.g. 1 = -v -v is necessary to print info messages of the runtime system
##        2 = -v -v -v is necessary to print info messages of the runtime system
##
typeset -i __RT_VERBOSE_LEVEL=${__RT_VERBOSE_LEVEL:=1}

## __QUIET_MODE - do not print messages to STDOUT (def.: false)
##   use the parameter -q/+q to change this variable
##
__QUIET_MODE=${__QUIET_MODE:=${__FALSE}}

## __VERBOSE_MODE - print verbose messages (def.: false)
##   use the parameter -v/+v to change this variable 
##
__VERBOSE_MODE=${__VERBOSE_MODE:=${__FALSE}}

## __NO_TIME_STAMPS - Do not use time stamps in the messages (def.: false)
##
__NO_TIME_STAMPS=${__NO_TIME_STAMPS:=${__FALSE}}

## __NO_HEADERS - Do not print headers and footers (def.: false)
##
__NO_HEADERS=${__NO_HEADERS:=${__FALSE}}

## __FORCE - do the action anyway (def.: false)
##   If this variable is set to ${__TRUE} the function "die" will return
##   if called with an RC not zero (instead of aborting the script)
##   use the parameter -f/+f to change this variable
##
__FORCE=${__FALSE}

## __USE_COLORS - use colors (def.: false)
##   use the parameter -a/+a to change this variable
##
__USE_COLORS=${__USE_COLORS:=${__FALSE}}

## __USER_BREAK_ALLOWED - CTRL-C aborts the script or not (def.: true)
##   (no parameter to change this variable)
##
__USER_BREAK_ALLOWED=${__USER_BREAK_ALLOWED:=${__TRUE}}

## __NOECHO - turn echo on while reading input from the user
##   do not echo the user input in AskUser if __NOECHO is set to ${__TRUE}
##
__NOECHO=${__FALSE}

## __USE_TTY - write prompts and read user input from /dev/tty (def.: false)
##   If __USE_TTY is ${__TRUE} the function AskUser writes the prompt to /dev/tty
##   and the reads the user input from /dev/tty . This is useful if STDOUT is
##   redirected to a file.
##
__USE_TTY=${__FALSE}

## __OVERWRITE mode - overwrite existing files or not (def.: false)
##   use the parameter -O/+O to change this variable
##
__OVERWRITE_MODE=${__OVERWRITE_MODE:=${__FALSE}}

## __DEBUG_MODE - use single step mode for main (def.: false)
##   use the parameter -D/+D to change this variable
##
__DEBUG_MODE=${__FALSE}
__SCRIPT_ARRAY[0]=0

## __TEMPDIR - directory for temporary files
##
__TEMPDIR="${TMP:-${TEMP:-/tmp}}"

## __NO_OF_TEMPFILES
##   number of automatically created tempfiles that are deleted at program end
##   (def. 2)
##   Note: The variable names for the tempfiles are __TEMPFILE1, __TEMPFILE2, etc.
##
__NO_OF_TEMPFILES=2

## __LIST_OF_TMP_MOUNTS - list of mounts that should be umounted at program end
##
__LIST_OF_TMP_MOUNTS=""

## __LIST_OF_TMP_DIRS - list of directories that should be removed at program end
##
__LIST_OF_TMP_DIRS=""

## __LIST_OF_TMP_FILES - list of files that should be removed at program end
##
__LIST_OF_TMP_FILES=""

## __EXITROUTINES - list of routines that should be executed before the script ends
##
__EXITROUTINES=""

## __REBOOT_REQUIRED - set to true to reboot automatically at
##   script end (def.: false)
##
__REBOOT_REQUIRED=${__FALSE}

## __REBOOT_PARAMETER - parameter for the reboot command (def.: none)
##
__REBOOT_PARAMETER=""

## __PRINT_LIST_OF_WARNINGS_MSGS - print the list of warning messages at program end (def.: false)
##
__PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE}

## __PRINT_LIST_OF_ERROR_MSGS - print the list of error messages at program end (def.: false)
##
__PRINT_LIST_OF_ERROR_MSGS=${__FALSE}

## __PRINT_SUMMARIES - print error/warning msg summaries at script end
##
##   print error and/or warning message summaries at program end
##   known values:
##       0 = do not print summaries
##       1 = print error msgs,
##       2 = print warning msgs
##       3 = print error and warning mgs
##   use the parameter -S to change this variable
##
__PRINT_SUMMARIES=0

## __MAINRC - return code of the program
##
__MAINRC=0


# -----------------------------------------------------------------------------
#

# -----------------------------------------------------------------------------
# init the global variables
#

## ##### defined variables that should not be changed
##

# init the variable for the TRAP handlers 
#   __INCLUDE_SCRIPT_RUNNING contains the name of the included script if
#   a sourced-in script is currently running
#
  __INCLUDE_SCRIPT_RUNNING=""

#
# internal variables for push/pop
#
typeset -i __STACK_POINTER=0
__STACK[0]=${__STACK_POINTER}

#
# internal variables for the single-step routine
#
typeset -i __BREAKPOINT_LINE=0
typeset -i __STEP_COUNT=0
typeset -i __TRACE_COUNT=0
__DEBUG_HISTFILE="/tmp/ksh.history.$$"

# delete the history file used in the debug routine at program end
__LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} ${__DEBUG_HISTFILE}"

# variable used for input by the user
#
__USER_RESPONSE_IS=""

# __STTY_SETTINGS
#   saved stty settings before switching off echo in AskUser
#
__STTY_SETTINGS=""

## __SCRIPTNAME - name of the script without the path
##
typeset -r __SCRIPTNAME="${0##*/}"

## __SCRIPTDIR - path of the script (as entered by the user!)
##
__SCRIPTDIR="${0%/*}"

## __REAL_SCRIPTDIR - path of the script (real path, maybe a link)
##
__REAL_SCRIPTDIR=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )

## __CONFIG_FILE - name of the config file
##   (use ReadConfigFile to read the config file;
##   use WriteConfigFile to write it)
##
__CONFIG_FILE="${__SCRIPTNAME%.*}.conf"

## __HOSTNAME - hostname
##
__HOSTNAME="$( uname -n )"

## __NODENAME - nodename
##
__NODENAME=${__HOSTNAME}
[ -f /etc/nodename ] && __NODENAME="$( cat /etc/nodename )"

## __OS - Operating system (e.g. SunOS)
##
__OS="$( uname -s )"

## __ZONENAME - name of the current zone if running in Solaris 10 or newer
##

## __OS_VERSION - Operating system version (e.g 5.8)
##

## __OS_RELEASE - Operating system release (e.g. Generic_112233-08)
##

## __MACHINE_CLASS - Machine class (e.g sun4u)
##

## __MACHINE_PLATFORM - hardware platform (e.g. SUNW,Ultra-4)
##

## __MACHINE_SUBTYPE - machine type (e.g  Sun Fire 3800)
##

## __MACHINE_ARC - machine architecture (e.g. sparc)
##

## __RUNLEVEL - current runlevel
##
# __RUNLEVEL=$( set -- $( who -r )  ; echo $7 )

case ${__OS} in

    "SunOS" )
       __ZONENAME="$( zonename 2>/dev/null )"
       __OS_VERSION="$( uname -r )"
       __MACHINE_CLASS="$( uname -v )"
       __MACHINE_CLASS="$( uname -m )"
       __MACHINE_PLATFORM="$( uname -i )"
       [  -x /usr/platform/${__MACHINE_PLATFORM}/sbin/prtdiag ] &&   \
         ( set -- $( /usr/platform/${__MACHINE_PLATFORM}/sbin/prtdiag | grep "System Configuration" ) ; shift 5; echo $* ) 2>/dev/null | read  __MACHINE_SUBTYPE
         __MACHINE_ARC="$( uname -p )"
    __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f8 -d " " )
      ;;
    
     "AIX" )
        __ZONENAME=""
         __MACHINE_PLATFORM="$( oslevel )"
	 __OS_VERSION="$( oslevel -r )"
	 __MACHINE_CLASS="$( uname -m )"
	 __MACHINE_PLATFORM="$( uname -M )"
	 __MACHINE_SUBTYPE=""
         __MACHINE_ARC="$( uname -p )"
         __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f8 -d " " )
	 ;;

     
   "Linux" )
     __ZONENAME=""
     __OS_VERSION="$( uname -r )"
     __MACHINE_CLASS="$( uname -m )"
     __MACHINE_CLASS="$( uname -m )"
     __MACHINE_PLATFORM="$( uname -i )"
     __MACHINE_SUBTYPE=""
     __MACHINE_ARC="$( uname -p )"
    __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f3 -d " " )
     ;;
    
             * )
     __ZONENAME=""
     __OS_VERSION=""
     __MACHINE_CLASS=""
     __MACHINE_PLATFORM=""
     __MACHINE_SUBTYPE=""
     __MACHINE_ARC=""
     __RUNLEVEL="?"
     ;;
    
esac


## __START_DIR - working directory when starting the script
##
__START_DIR="$( pwd )"

## __LOGFILE - fully qualified name of the logfile used
##   use the parameter -l to change the logfile
##
if [ -d /var/tmp ] ; then
  __DEF_LOGFILE="/var/tmp/${__SCRIPTNAME%.*}.LOG"
else
  __DEF_LOGFILE="/tmp/${__SCRIPTNAME%.*}.LOG"
fi

__LOGFILE="${__DEF_LOGFILE}"

# __GLOBAL_OUTPUT_REDIRECTION
#   status variable used by StartStop_LogAll_to_logfile
#
__GLOBAL_OUTPUT_REDIRECTION=""

    
# lock file (used if ${__ONLY_ONCE} is ${__TRUE})
# Note: This is only a symbolic link
#
__LOCKFILE="/tmp/${__SCRIPTNAME}.lock"
__LOCKFILE_CREATED=${__FALSE}

## __NO_OF_WARNINGS - Number of warnings found
##
typeset -i __NO_OF_WARNINGS=0

## __LIST_OF_WARNINGS - List of warning messages
##
__LIST_OF_WARNINGS=""

## __NO_OF_ERRORS - Number of errors found
##
typeset -i __NO_OF_ERRORS=0

## __LIST_OF_ERRORS - List of error messages
##
__LIST_OF_ERRORS=""

## __LOGON_USERID - ID of the user opening the session 
##
__LOGIN_USERID=$( set -- $( who am i ) ; echo $1 )
[ "${__LOGIN_USERID}" = "" ] && __LOGIN_USERID=${LOGNAME}

## __USERID - ID of the user executing this script (e.g. xtrnaw7)
##
__USERID=${__LOGIN_USERID}
if [ "${__OS}"x = "SunOS"x ] ; then
  [ -x /usr/ucb/whoami ] && __USERID=$( /usr/ucb/whoami )
else
  __USERID=$( whoami )
fi


# -----------------------------------------------------------------------------
# color variables

## Foreground Color variables:
## __COLOR_FG_BLACK, __COLOR_FG_RED,     __COLOR_FG_GREEN, __COLOR_FG_YELLOW
## __COLOR_FG_BLUE,  __COLOR_FG_MAGENTA, __COLOR_FG_CYAN,  __COLOR_FG_WHITE
##
## Background Color variables:
## __COLOR_BG_BLACK, __COLOR_BG_RED,     __COLOR_BG_GREEN, __COLOR_BG_YELLOW
## __COLOR_BG_BLUE,  __COLOR_BG_MAGENTA, __COLOR_BG_CYAN,  __COLOR_BG_WHITE
##

__COLOR_FG_BLACK="\033[30m"
__COLOR_FG_RED="\033[31m"
__COLOR_FG_GREEN="\033[32m"
__COLOR_FG_YELLOW="\033[33m"
__COLOR_FG_BLUE="\033[34m"
__COLOR_FG_MAGENTA="\033[35m"
__COLOR_FG_CYAN="\033[36m"
__COLOR_FG_WHITE="\033[37m"

__COLOR_BG_BLACK="\033[40m"
__COLOR_BG_RED="\033[41m"
__COLOR_BG_GREEN="\033[42m"
__COLOR_BG_YELLOW="\033[43m"
__COLOR_BG_BLUE="\033[44m"
__COLOR_BG_MAGENTA="\033[45m"
__COLOR_BG_CYAN="\033[46m"
__COLOR_BG_WHITE="\033[47m"

##
## Colorattributes:
## __COLOR_OFF, __COLOR_BOLD, __COLOR_NORMAL, - normal, __COLOR_UNDERLINE
## __COLOR_BLINK, __COLOR_REVERSE, __COLOR_INVISIBLE
##

__COLOR_BOLD="\033[1m"
__COLOR_NORMAL="\033[2m"
__COLOR_UNDERLINE="\033[4m"
__COLOR_BLINK="\033[5m"
__COLOR_REVERSE="\033[7m"
__COLOR_INVISIBLE="\033[8m"
__COLOR_OFF="\033[0;m"


# position cursor:       ESC[row,colH or ESC[row;colf  (1,1 = upper left corner)
# Clear rest of line:    ESC[K
# Clear screen:          ESC[2J
# Save Cursor Pos        ESC[s
# Restore Cursor Pos     ESC[u
# Cursor Up # lines      ESC{colsA
# Cursor down # lines    ESC{colsB
# Cursor right # columns ESC{colsC
# Cursor left # columns  ESC{colsD
# Get Cursor Pos         ESC[6n
#

# -----------------------------------------------------------------------------

##
## ##### defined sub routines
##

## --------------------------------------
## ReadConfigFile
##
## read the config file
##
## usage: ReadConfigFile [configfile]
##
## where:   configfile - name of the config file
##          default: search ${__CONFIG_FILE} in the current directory,
##          in the home directory, and in /etc (in this order)
##
## returns: ${__TRUE} - ok config read
##          ${__FALSE} - error config file not found or not readable
##
ReadConfigFile() {
  typeset __FUNCTION="ReadConfigFile"; ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THIS_CONFIG="$1"
  typeset THISRC=${__FALSE}
 
  if [ "${THIS_CONFIG}"x = ""x ] ; then
    THIS_CONFIG="./${__CONFIG_FILE}"
    [ ! -f "${THIS_CONFIG}" ] && THIS_CONFIG="${HOME}/${__CONFIG_FILE}"
    [ ! -f "${THIS_CONFIG}" ] && THIS_CONFIG="/etc/${__CONFIG_FILE}"
  fi

  if [ -f "${THIS_CONFIG}" ] ; then
    LogHeader "Reading the config file \"${THIS_CONFIG}\" ..."

    includeScript "${THIS_CONFIG}"

    THISRC=${__TRUE}   
  else
    LogHeader "No config file (\"${__CONFIG_FILE}\") found (use -C to create a default config file)"
  fi

  return ${THISRC}
}

## --------------------------------------
## WriteConfigFile
##
## write the variable ${__CONFIG_PARAMETER} to the config file
##
## usage: WriteConfigFile [configfile]
##
## where:  configfile - name of the config file
##         default: write ${__CONFIG_FILE} in the current directory
##
## returns: ${__TRUE} - ok config file written
##          ${__FALSE} - error writing the config file
##
WriteConfigFile() {
  typeset __FUNCTION="WriteConfigFile" ; ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THIS_CONFIG_FILE="$1"
  typeset THISRC=${__FALSE}
 
  [ "${THIS_CONFIG_FILE}"x = ""x ] && THIS_CONFIG_FILE="./${__CONFIG_FILE}"

  [ -f "${THIS_CONFIG_FILE}" ] &&  BackupFileIfNecessary "${THIS_CONFIG_FILE}"
  LogMsg "Writing the config file \"${THIS_CONFIG_FILE}\" ..."
  
cat <<EOT >"${THIS_CONFIG_FILE}"
# config file for $0
${__CONFIG_PARAMETER}
EOT
  THISRC=$?
 
  return ${THISRC}
}

## --------------------------------------
## NoOfStackElements
##
## return the no. of stack elements
##
## usage: NoOfStackElements; var=$?
##
## returns: no. of elements on the stack
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
NoOfStackElements() {
  typeset __FUNCTION="NoOfStackElements";  ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  return ${__STACK_POINTER}
}

## --------------------------------------
## FlushStack
##
## flush the stack
##
## usage: FlushStack
##
## returns: no. of elements on the stack before flushing it
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
FlushStack() {
  typeset __FUNCTION="FlushStack";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=${__STACK_POINTER}
  __STACK_POINTER=0
  return ${THISRC}
}

## --------------------------------------
## push
##
## push one or more values on the stack
##
## usage: push value1 [...] [value#]
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
push() {
  typeset __FUNCTION="push";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

   while [ $# -ne 0 ] ; do
    (( __STACK_POINTER=__STACK_POINTER+1 ))
    __STACK[${__STACK_POINTER}]="$1"
    shift
  done

  return 0
}

## --------------------------------------
## pop
##
## pop one or more values from the stack
##
## usage: pop variable1 [...] [variable#]
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
pop() {
  typeset __FUNCTION="pop";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset NEWALUE=""

  while [ $# -ne 0 ] ; do
    if [ ${__STACK_POINTER} -eq 0 ] ; then
      NEWVALUE=""
    else
      NEWVALUE="${__STACK[${__STACK_POINTER}]}"
      (( __STACK_POINTER=__STACK_POINTER-1 ))
    fi
    eval $1="\"${NEWVALUE}\""
    shift
  done

  return 0
}

## --------------------------------------
## push_and_set
##
## push a variable to the stack and set the variable to a new value
##
## usage: push_and_set variable new_value
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
push_and_set() {
  typeset __FUNCTION="push_and_set";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ $# -ne 0 ] ; then
    typeset VARNAME="$1"
    eval push \$${VARNAME}
    
    shift
    eval ${VARNAME}="\"$*\""
  fi
 
  return 0
}


## --------------------------------------
## CheckYNParameter
##
## check if a parameter is y, n, 0, or 1
##
## usage: CheckYNParameter parameter
##
## returns: ${__TRUE} - the parameter is equal to yes
##          ${__FALSE} - the parameter is equal to no
##
CheckYNParameter(){
  typeset __FUNCTION="CheckYNParameter";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=255
 
  case $1 in
   "y" | "Y" | "yes" | "YES" | "true"  | "TRUE"  | 0 ) THISRC=${__TRUE} ;;
   "n" | "N" | "no"  | "NO"  | "false" | "FALSE" | 1 ) THISRC=${__FALSE} ;;
   * ) THISRC=255 ;;
  esac
  return ${THISRC}
}


## --------------------------------------
## ConvertToYesNo
##
## convert the value of a variable to y or n
##
## usage: ConvertToYesNo parameter
##
## returns: 0
##          prints y, n or ? to STDOUT
##
ConvertToYesNo(){
  typeset __FUNCTION="ConvertToYesNo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  case $1 in
   "y" | "Y" | "yes" | "YES" | "true"  | "TRUE"  | 0 ) echo "y" ;;
   "n" | "N" | "no"  | "NO"  | "false" | "FALSE" | 1 ) echo "n" ;;
   * ) echo "?" ;;
  esac
 
  return 0
}

## --------------------------------------
## InvertSwitch
##
## invert a switch from true to false or vice versa
##
## usage: InvertSwitch variable
##
## returns 0
##         switch the variable "variable" from ${__TRUE} to
##         ${__FALSE} or vice versa
##
InvertSwitch(){
  typeset __FUNCTION="InvertSwitch";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "[ \$$1 -eq ${__TRUE} ] && $1=${__FALSE} || $1=${__TRUE} "
 
  return 0
}

 
## --------------------------------------
## CheckInputDevice
##
## check if the input device is a terminal
##
## usage: CheckInputDevice
##
## returns: 0 - the input device is a terminal (interactive)
##          1 - the input device is NOT a terminal
##
CheckInputDevice(){
  typeset __FUNCTION="CheckInputDevice";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  tty -s
  return $?
}
 
## --------------------------------------
## GetProgramDirectory
##
## get the directory where a program resides
##
## usage: GetProgramDirectory [programpath/]programname [resultvar]
##
## returns: 0
##          the variable PRGDIR contains the directory with the program
##          if the parameter resultvar is missing
##
GetProgramDirectory() {
  typeset __FUNCTION="GetProgramDirectory";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset PRG=""
  typeset RESULTVAR=$2
   
  if [ ! -L $1 ] ; then
    PRG=$( cd -P -- "$(dirname -- "$(command -v -- "$1")")" && pwd -P )
  else 
# resolve links - $1 may be a softlink
    PRG="$1"
  
    while [ -h "$PRG" ] ; do
      ls=$(ls -ld "$PRG")
      link=$( expr "$ls" : '.*-> \(.*\)$' )
      if expr "$link" : '.*/.*' > /dev/null; then
        PRG="$link"
      else
        PRG=$(dirname "$PRG")/"$link"
      fi
    done
    PRG="$(dirname ${PRG})"
  fi

  if [ "${RESULTVAR}"x != ""x ] ; then
     eval ${RESULTVAR}=\"${PRG}\"
  else
    PRGDIR="${PRG}"
  fi
 
  return 0
}

## --------------------------------------
## substr
##
## get a substring of a string
##
## usage: variable=$( substr sourceStr pos length )
##     or substr sourceStr pos length resultStr
##
## returns: 1 - parameter missing
##          0 - parameter okay
##
substr() {
  typeset __FUNCTION="substr";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset resultstr=""
  typeset THISRC=1

  if [ "$1"x != ""x ] ; then
    typeset s="$1"
    typeset p="$2"
    typeset l="$3"
    [ "$l"x = ""x ] && l=${#s}
    [ "$p"x = ""x ] && p=1
    resultstr="$( echo $s | cut -c${p}-$((${p}+${l}-1)) )"
    THISRC=0
  else
    THISRC=1
    resultstr="$1"
  fi

  if [ "$4"x != ""x ] ; then
    eval $4=\"${resultstr}\"
  else
    echo "${resultstr}"
  fi

  return ${THISRC}
}

## --------------------------------------
## replacestr
##
## replace a substring with another substring
##
## usage: variable=$( replacestr sourceStr oldsubStr newsubStr )
##     or replacestr sourceStr oldsubStr newsubStr resultvariable
##
## returns: 0 - substring replaced
##          1 - substring not found
##          3 - error, parameter missing
##
##          writes the substr to STDOUT if resultvariable is missing
##
replacestr() {
  typeset __FUNCTION="replacestr";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=3
  
  typeset sourcestring="$1"
  typeset oldsubStr="$2"
  typeset newsubStr="$3"

  if [ "${sourcestring}"x != ""x -a "${oldsubStr}"x != ""x ] ; then
    if [[ "${sourcestring}" == *${oldsubStr}* ]] ; then
      sourcestring="${sourcestring%%${oldsubStr}*}${newsubStr}${sourcestring#*${oldsubStr}}"
      THISRC=0
    else
      THISRC=1
    fi
  fi

  if [ "$4"x != ""x ] ; then
    eval $4=\"${sourcestring}\"
  else
    echo "${sourcestring}"
  fi

  return ${THISRC}
}

## --------------------------------------
## pos
##
## get the first position of a substring in a string
##
## usage: pos searchstring sourcestring
##
## returns: 0 - searchstring is not part of sourcestring
##          else the position of searchstring in sourcestring
##
pos() {
  typeset __FUNCTION="pos";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset searchstring="$1"
  typeset sourcestring="$2"

  if [[ "${sourcestring}" == *${searchstring}* ]] ; then
    typeset f="${sourcestring%%${searchstring}*}"
    return $((  ${#f}+1 ))
  else
    return 0
  fi
}

## --------------------------------------
## lastpos
##
## get the last position of a substring in a string
##
## usage: lastpos searchstring sourcestring
##
## returns: 0 - searchstring is not part of sourcestring
##          else the position of searchstring in sourcestring
##
lastpos() {
  typeset __FUNCTION="lastpos";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset searchstring="$1"
  typeset sourcestring="$2"

  if [[ "${sourcestring}" == *${searchstring}* ]] ; then
    typeset f="${sourcestring%${searchstring}*}"
    return $((  ${#f}+1 ))
  else
    return  0
  fi
}


## --------------------------------------
## isNumber
##
## check if a value is an integer
##
## usage: isNumber testValue
##
## returns: ${__TRUE} - testValue is a number else not
##
isNumber() {
  typeset __FUNCTION="isNumber";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

## --------------------------------------
## ConvertToHex
##
## convert the value of a variable to a hex value
##
## usage: ConvertToHex value
##
## returns: 0
##          prints the value in hex to STDOUT
##
ConvertToHex(){
  typeset __FUNCTION="ConvertToHex";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i16 HEXVAR
  HEXVAR="$1"
  echo ${HEXVAR##*#}
 
  return 0
} 

## --------------------------------------
## ConvertToOctal
##
## convert the value of a variable to a octal value
##
## usage: ConvertToOctal value
##
## returns: 0
##          prints the value in octal to STDOUT
##
ConvertToOctal(){
  typeset __FUNCTION="ConvertToOctal";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i8 OCTVAR
  OCTVAR="$1"
  echo ${OCTVAR##*#}
 
  return 0
} 

## --------------------------------------
## ConvertToBinary
##
## convert the value of a variable to a binary value
##
## usage: ConvertToBinary value
##
## returns: 0
##          prints the value in binary to STDOUT
##
ConvertToBinary(){
  typeset __FUNCTION="ConverToBinary";  ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i2 BINVAR
  BINVAR="$1"
  echo ${BINVAR##*#}
 
  return 0
} 


## --------------------------------------
## toUppercase
##
## convert a string to uppercase
##
## usage: toUppercase sourceString | read resultString
##    or   targetString=$( toUppercase sourceString )
##    or   toUppercase sourceString resultString
##
## returns: 0
##          writes the converted string to STDOUT if resultString is missing
##
toUppercase() {
  typeset __FUNCTION="toUppercase";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -u testvar="$1"

  if [ "$2"x != ""x ] ; then
    eval $2=\"${testvar}\"
  else
    echo "${testvar}"
  fi
 
  return 0
}

## --------------------------------------
## toLowercase
##
## convert a string to lowercase
##
## usage: toLowercase sourceString | read resultString
##    or   targetString=$( toLowercase sourceString )
##    or   toLowercase sourceString resultString
##
## returns: 0
##          writes the converted string to STDOUT if resultString is missing
##
toLowercase() {
  typeset __FUNCTION="toLowercase";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -l testvar="$1"

  if [ "$2"x != ""x ] ; then
    eval $2=\"${testvar}\"
  else
    echo "${testvar}"
  fi
 
  return 0
}


## --------------------------------------
## StartStop_LogAll_to_logfile
##
## redirect STDOUT and STDERR into a file
##
## usage: StartStop_LogAll_to_logfile [start|stop] logfile
##
## returns: 0 - okay, redirection started / stopped
##          1 - error, can not write to the logfile
##          2 - invalid usage (to much or not enough parameter)
##          3 - invalid parameter
##
## To explicitly write to STDOUT after calling this function with the
## parameter "start" use
##   echo "This goes to STDOUT" >&3
##
## To explicitly write to STDERR after calling this function with the
## parameter "start" use
##   echo "This goes to STDERR" >&4
##
StartStop_LogAll_to_logfile() {
  typeset __FUNCTION="StartStop_LogAll_to_logfile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=0
 
  if [ $# -ne 0 ] ; then
    case $1 in

     'start' )
        if [ $# -gt 1 ] ; then
          touch "$2" 2>/dev/null
          if [ $? -eq 0 ] ; then
            LogInfo "Logging STDOUT and STDERR to \"$2\" ... "
            exec 3>&1
            exec 4>&2
	    if [ "${__OVERWRITE_MODE}" = "${__TRUE}" ] ; then
              exec 1>$2 2>&1
	    else
              exec 1>>$2 2>&1
	    fi
	    __GLOBAL_OUTPUT_REDIRECTION="$2"
          else
            THISRC=1
          fi	
        else
	  THISRC=2
	fi
        ;;

      'stop' )
	if [ "${__GLOBAL_OUTPUT_REDIRECTION}"x != ""x ] ; then
          exec 2>&4
          exec 1>&3
          LogInfo "Stopping logging of STDOUT and STDERR to \"${__GLOBAL_OUTPUT_REDIRECTION}\""
          __GLOBAL_OUTPUT_REDIRECTION=
	fi  
        ;;

      * )
        THISRC=3
        ;;
    esac
  else
    THISRC=2
  fi

  return ${THISRC}
}

## --------------------------------------
## executeCommand
##
## execute a command
##
## usage: executeCommand command parameter
##
## returns: the RC of the executed command
##
executeCommand() {
  typeset __FUNCTION="executeCommand";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=0

  set +e

  LogRuntimeInfo "Executing \"$@\" " 

  eval "$@"
  THISRC=$?
 
  return ${THISRC}
}

## --------------------------------------
## executeCommandAndLog
##
## execute a command and write STDERR and STDOUT to the logfile
##
## usage: executeCommandAndLog command parameter
##
## returns: the RC of the executed command
##
executeCommandAndLog() {
  typeset __FUNCTION="executeCommandAndLog";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  set +e
  typeset THISRC=0

  LogRuntimeInfo "Executing \"$@\" " 

  if [ "${__LOGFILE}"x != ""x -a -f "${__LOGFILE}" ] ; then
    eval "$@" 2>&1 | tee -a "${__LOGFILE}"
    THISRC=$?
  else   
    eval "$@"
    THISRC=$?
  fi

  return ${THISRC}
}

## --------------------------------------
## executeCommandAndLogSTDERR
##
## execute a command and write STDERR to the logfile
##
## usage: executeCommandAndLogSTDERR command parameter
##
## returns: the RC of the executed command
##
executeCommandAndLogSTDERR() {
  typeset __FUNCTION="executeCommandAndLogSTDERR";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  set +e
  typeset THISRC=0

  LogRuntimeInfo "Executing \"$@\" "  >&2

  if [ "${__LOGFILE}"x != ""x -a -f" ${__LOGFILE}" ] ; then
    eval "$@" 2>>${__LOGFILE}
    THISRC=$?
  else   
    eval "$@"
    THISRC=$?
  fi

  return ${THISRC}
}

## --------------------------------------
## UserIsRoot
##
## validate the user id
##
## usage: UserIsRoot
##
## returns: ${__TRUE} - the user is root; else not
##
UserIsRoot() {
  typeset __FUNCTION="UserIsRoot";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$( id | sed 's/uid=\([0-9]*\)(.*/\1/' )" = 0 ] && return ${__TRUE} || return ${__FALSE}
}


## --------------------------------------
## UserIs
##
## validate the user id
##
## usage: UserIs USERID
##
## where: USERID - userid (e.g oracle)
##
## returns: 0 - the user is this user
##          1 - the user is NOT this user
##          2 - the user does not exist on this machine
##          3 - missing parameter
##
UserIs() {
  typeset __FUNCTION="UserIs";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=3
  typeset USERID=""
 
  if [ "$1"x != ""x ] ; then
    THISRC=2
    USERID=$( grep "^$1:" /etc/passwd | cut -d: -f3 )
    if [ "${USERID}"x != ""x ] ; then
      UID="$( id | sed 's/uid=\([0-9]*\)(.*/\1/' )"     
      [ ${UID} = ${USERID} ] && THISRC=0 || THISRC=1  
    fi
  fi

  return ${THISRC}
}

## --------------------------------------
## GetCurrentUID
##
## get the UID of the current user
##
## usage: GetCurrentUID
##
## where: -
##
## returns: the UID (e.g. 100)
##
GetCurrentUID() {
  typeset __FUNCTION="GetCurrentUID";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  return "$(id | sed 's/uid=\([0-9]*\)(.*/\1/')"
}

## --------------------------------------
## GetUserName
##
## get the name of a user
##
## usage: GetUserName UID
##
## where: UID - userid (e.g 1686)
##
## returns: 0
##          __USERNAME contains the user name or "" if
##           the userid does not exist on this machine
##
GetUserName() {
  typeset __FUNCTION="GetUserName";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$1"x != ""x ] &&  __USERNAME=$( grep ":$1:" /etc/passwd | cut -d: -f1 )  || __USERNAME=""
 
  return 0
}

## --------------------------------------
## GetUID
##
## get the UID for a username
##
## usage: GetUID username
##
## where: username - user name (e.g nobody)
##
## returns: 0
##          __USER_ID contains the UID or "" if
##          the username does not exist on this machine
##
GetUID() {
  typeset __FUNCTION="GetUID";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$1"x != ""x ] &&  __USER_ID=$( grep "^$1:" /etc/passwd | cut -d: -f3 ) || __USER_ID=""
 
  return 0
}


# ======================================

## --------------------------------------
## LogMsg
##
## print a message to STDOUT and write it also to the logfile
##
## usage: LogMsg message
##
## returns: 0
##
## Notes: Use - your message to suppress the date stamp
##        Use "-" to print a complete blank line
##
LogMsg() {
  typeset __FUNCTION="LogMsg";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ "$1"x = "-"x ] ; then
    shift
    typeset THISMSG="$*"
  elif [ "${__NO_TIME_STAMPS}"x = "${__TRUE}"x ] ; then
    typeset THISMSG="$*"
  else
    typeset THISMSG="[$(date +"%d.%m.%Y %H:%M:%S")] $*"
  fi
 
  [  ${__QUIET_MODE} -ne ${__TRUE} ] && echo "${THISMSG} "
  [ "${__LOGFILE}"x != ""x ] && [ -f "${__LOGFILE}" ] &&  echo "${THISMSG}" >>${__LOGFILE}
 
  return 0
}


## --------------------------------------
## LogOnly
##
## write a message to the logfile
##
## usage: LogOnly message
##
## returns: 0
##
LogOnly() {
  typeset __FUNCTION="LogOnly";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISMSG="[$(date +"%d.%m.%Y %H:%M:%S")] $*"

  [ "${__LOGFILE}"x != ""x ] && [ -f "${__LOGFILE}" ] &&  echo "${THISMSG}" >>${__LOGFILE}
 
  return 0
}

## --------------------------------------
## LogInfo
##
## print a message to STDOUT and write it also to the logfile
## only if in verbose mode
##
## usage: LogInfo [loglevel] message
##
## returns: 0
##
## Notes: Output goes to STDERR, default loglevel is 0
##
LogInfo() {
  typeset __FUNCTION="LogInfo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

#  [ ${__VERBOSE_MODE} -eq ${__TRUE} ] && LogMsg "INFO: $*"

  typeset THISLEVEL=0
 
  if [ ${__VERBOSE_MODE} -eq ${__TRUE} ] ; then
    if [ $# -gt 1 ] ; then
      isNumber $1
      if [ $? -eq ${__TRUE} ] ; then
        THISLEVEL=$1
        shift
      fi
    fi     
    [ ${__VERBOSE_LEVEL} -gt ${THISLEVEL} ]  && LogMsg "INFO: $*" >&2
  fi 
  return 0
  }

# internal sub routine for info messages
#
#
LogRuntimeInfo() {
  typeset __FUNCTION="LogRuntimeInfo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}
  LogInfo "${__RT_VERBOSE_LEVEL}" "$*"
  return 0
}

# internal sub routine for header messages
#
#
LogHeader() {
  [ "${__NO_HEADERS}"x != "${__TRUE}"x ] && LogMsg "$*"
  return 0
}

## --------------------------------------
## LogWarning
##
## print a warning to STDERR and write it also to the logfile
##
## usage: LogWarning message
##
## returns: 0
##
## Notes: Output goes to STDERR
##
LogWarning() {
  typeset __FUNCTION="LogWarning";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  LogMsg "WARNING: $*" >&2
  (( __NO_OF_WARNINGS = __NO_OF_WARNINGS +1 ))
  __LIST_OF_WARNINGS="${__LIST_OF_WARNINGS}
WARNING: $*" 
  return 0
}

## --------------------------------------
## LogError
##
## print an error message to STDERR and write it also to the logfile
##
## usage: LogError message
##
## returns: 0
##
## Notes: Output goes to STDERR
##
LogError() {
  typeset __FUNCTION="LogError";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  LogMsg "ERROR: $*" >&2

  (( __NO_OF_ERRORS=__NO_OF_ERRORS + 1 )) 
  __LIST_OF_ERRORS="${__LIST_OF_ERRORS}
ERROR: $*" 
  return 0
}


## ---------------------------------------
## BackupFileIfNecessary
##
## create a backup of a file if ${__OVERWRITE_MODE} is set to ${__FALSE}
##
## usage: BackupFileIfNecessary [file1} ... {filen}
##
## returns: 0 - done; else error
##
BackupFileIfNecessary() {
  typeset __FUNCTION="BackupFileIfNecessary";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

 [ "${BACKUP_EXTENSION}"x = ""x ] && BACKUP_EXTENSION=".$$"

 typeset FILES_TO_BACKUP="$*"
 typeset CURFILE=""
 typeset CUR_BKP_FILE=""
 typeset THISRC=0
 
 if [ ${__OVERWRITE_MODE} -eq ${__FALSE} ] ; then
   for CURFILE in ${FILES_TO_BACKUP} ; do        
     [ ! -f "${CURFILE}" ] && continue

     CUR_BKP_FILE="${CURFILE}${BACKUP_EXTENSION}"
     LogMsg "Creating a backup of \"${CURFILE}\" in \"${CUR_BKP_FILE}\" ..."
     cp "${CURFILE}" "${CUR_BKP_FILE}"
     THISRC=$?
     if [ ${THISRC} -ne 0 ] ; then
       LogError "Error creating the backup of the file \"${CURFILE}\""
       break
     fi
   done
 fi

 return ${THISRC}
} 

## ---------------------------------------
## CopyDirectory
##
## copy a directory
##
## usage: CopyDirectory sourcedir targetDir
##
## returns:  0 - done;
##           else error
##
CopyDirectory() {
  typeset __FUNCTION="CopyDirectory";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=1
  if [ "$1"x != ""x -a "$2"x != ""x  ] ; then
     if [ -d "$1" -a -d "$2" ] ; then
        LogMsg "Copying all files from \"$1\" to \"$2\" ..."
        cd "$1"
        find . -depth -print | cpio -pdumv "$2"
        THISRC=$?
        cd "${OLDPWD}"
     fi
  fi

  return ${THISRC}
}


## --------------------------------------
## AskUser
##
## Ask the user (or use defaults depending on the parameter -n and -y)
##
## Usage: AskUser "message"
##       
## returns: ${__TRUE} - user input is yes
##          ${__FALSE} - user input is no
##          USER_INPUT contains the user input
##
## Notes: "all" is interpreted as yes for this and all other questions
##        "none" is interpreted as no for this and all other questions
##
## If __NOECHO is ${__TRUE} the user input is not written to STDOUT
## __NOECHO is set to ${__FALSE} again in this function
##
## If __USE_TTY is ${__TRUE} the prompt is written to /dev/tty and the
## user input is read from /dev/tty . This is useful if STDOUT is redirected
## to a file.
##
AskUser() {
  typeset __FUNCTION="AskUser";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=""

  if [ "${__USE_TTY}"x = "${__TRUE}"x ] ; then
    typeset mySTDIN="</dev/tty"
    typeset mySTDOUT=">/dev/tty"
  else
    typeset mySTDIN=""
    typeset mySTDOUT=""
  fi
 
  case ${__USER_RESPONSE_IS} in
    
   "y" ) USER_INPUT="y" ; THISRC=${__TRUE}
         ;;

   "n" ) USER_INPUT="n" ; THISRC=${__FALSE}
         ;;
  
     * ) [ $# -ne 0 ] && eval LogMsg "-" "\"$* \c\"" ${mySTDOUT}
          if [ ${__NOECHO} = ${__TRUE} ] ; then
            __STTY_SETTINGS="$( stty -g )"
            stty -echo
          fi
          eval read USER_INPUT ${mySTDIN}
          if [ ${__NOECHO} = ${__TRUE} ] ; then
            stty ${__STTY_SETTINGS}
            __STTY_SETTINGS=""
          fi

         case ${USER_INPUT} in

           "y" | "Y" ) THISRC=${__TRUE}  ;;

           "n" | "N" ) THISRC=${__FALSE} ;;

           "all" ) __USER_RESPONSE_IS="y"  ; THISRC=${__TRUE}  ;;

           "none" )  __USER_RESPONSE_IS="n" ;  THISRC=${__FALSE} ;;

           * )  THISRC=${__FALSE} ;;

        esac
        ;;
  esac 

  __NOECHO=${__FALSE}
  return ${THISRC}
}

## --------------------------------------
## GetKeystroke
##
## read one key from STDIN
##
## Usage: GetKeystroke "message"
##       
## returns: 0
##          USER_INPUT contains the user input
##         
GetKeystroke () {
  typeset __FUNCTION="GetKeystroke";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  trap "" 2 3
  [ $# -ne 0 ] && LogMsg "${THISMSG}"

  __STTY_SETTINGS="$( stty -g )"

  stty -echo raw
  USER_INPUT=$( dd count=1 2> /dev/null )

  stty ${__STTY_SETTINGS}
  __STTY_SETTINGS=""

  trap 2 3
 
  return 0
}

## --------------------------------------
## RebootIfNecessary
##
## Check if a reboot is necessary
##
## Usage: RebootIfNecessary
##
## Notes
##   The routine asks the user if neither the parameter -y nor the
##   parameter -n is used
##   Before using this routine uncomment the reboot command!
##
RebootIfNecessary() {
  typeset __FUNCTION="RebootIfNecessary";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ ${__REBOOT_REQUIRED} -eq 0 ] ; then
    LogMsg "The changes made to the system require a reboot"

    AskUser "Do you want to reboot now (y/n, default is NO)?"
    if [ $? -eq ${__TRUE} ] ; then
      LogMsg "Rebooting now ..."
      echo "???" reboot ${__REBOOT_PARAMETER}
    fi
  fi
 
  return 0
}

## ---------------------------------------
## die
##
## print a message and end the program
##
## usage: die returncode {message}
##
## returns: $1 (if it returns)
##
## Notes:
##
## This routine
##     - calls cleanup
##     - prints an error message if any (if returncode is not zero)
##       or the message if any (if returncode is zero)
##     - prints all warning messages again if ${__PRINT_LIST_OF_WARNING_MSGS}
##       is ${__TRUE}
##     - prints all error messages again if ${__PRINT_LIST_OF_ERROR_MSGS}
##       is ${__TRUE}
##     - prints a program end message and the program return code
## and
##     - and ends the program
##
## If the variable ${__FORCE} is ${__TRUE} and the return code is NOT zero
## die() will only print the error message and return
##
die() {
  typeset __FUNCTION="die";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  LogRuntimeInfo "__TRAP_SIGNAL is \"${__TRAP_SIGNAL}\""
 
  typeset THISRC=$1
  shift
  if [ "$*"x != ""x ] ; then
    [ ${THISRC} = 0 ] && LogMsg "$*" || LogError "$*"
  fi

  [ ${__FORCE} = ${__TRUE} -a ${THISRC} != 0 ] && return

  cleanup
 
  if [ "${__NO_OF_WARNINGS}" != "0" -a ${__PRINT_LIST_OF_WARNINGS_MSGS} -eq ${__TRUE} ] ; then
    LogMsg "*** CAUTION: One or more WARNINGS found ***"
    LogMsg "*** please check the logfile ***"
   
    LogMsg "Summary of warnings:
${__LIST_OF_WARNINGS}
"
  fi   

  if [ "${__NO_OF_ERRORS}" != "0" -a ${__PRINT_LIST_OF_ERROR_MSGS} -eq ${__TRUE} ] ; then
    LogMsg "*** CAUTION: One or more ERRORS found ***"
    LogMsg "*** please check the logfile ***"

    LogMsg "Summary of error messages
${__LIST_OF_ERRORS}
"
  fi   

  [[ -n "${__LOGFILE}" ]] && LogHeader "The log file used was \"${__LOGFILE}\" "
  __QUIET_MODE=${__FALSE}
  LogHeader "${__SCRIPTNAME} ended on $( date )."
  LogHeader "The RC is ${THISRC}."
 
  __EXIT_VIA_DIE=${__TRUE}

  StartStop_LogAll_to_logfile "stop"

  RebootIfNecessary
 
  exit ${THISRC}
}


## ---------------------------------------
## includeScript
##
## include a script via . [scriptname]
##
## usage: includeScript [scriptname]
##
## returns: 0
##
## notes:
##
includeScript() {
  typeset __FUNCTION="includeScript";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ $# -ne 0 ] ; then
  
    LogRuntimeInfo "Including the script \"$*\" ..."

# set the variable for the TRAP handlers
    [ ! -f "$1" ] && die 247 "Include script \"$1\" not found"
    __INCLUDE_SCRIPT_RUNNING="$1"
 
# include the script
    . $*

# reset the variable for the TRAP handlers 
    __INCLUDE_SCRIPT_RUNNING=""

  fi
}

# ======================================

##
## ##### defined internal sub routines (do NOT use; these routines are called
##       by the runtime system!)
##

# --------------------------------------
## CreateLockFile
#
# Create the lock file (which is really a symbolic link) if possible
#
# usage: CreateLockFile
#
# returns: 0 - lock created
#          1 - lock already exist or erro creating the lock
#
# Note: Use a symbolic link because this is always a atomic operation
#
CreateLockFile() {
  typeset __FUNCTION="CreateLockFile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset LN_RC=""

  ln -s  "$0" "${__LOCKFILE}" 2>/dev/null
  LN_RC=$?
     
  if [ ${LN_RC} = 0 ] ; then
    __LOCKFILE_CREATED=${__TRUE}
    return 0
  else
    return 1
  fi
}

# --------------------------------------
## RemoveLockFile
#
# Remove the lock file if possible
#
# usage: RemoveLockFile
#
# returns: 0 - lock file removed
#          1 - lock file does not exist
#          2 - error removing the lock file
#
RemoveLockFile() {
  typeset __FUNCTION="RemoveLockFile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ ! -L "${__LOCKFILE}" ] && return 1
  if [ ${__LOCKFILE_CREATED} -eq ${__TRUE} ] ; then
    rm "${__LOCKFILE}" 1>/dev/null 2>/dev/null
    [ $? -eq 0 ] && return 0
  fi 
  return 2
}

# ======================================

# --------------------------------------
## CreateTemporaryFiles
#
# create the temporary files
#
# usage: CreateTemporaryFiles
#
# returns: 0
#
# notes:
#  The variables with the tempfiles are called
#  __TEMPFILE1, __TEMPFILE2, ..., __TEMPFILE#
#
CreateTemporaryFiles() {
  typeset __FUNCTION="CreateTemporaryFiles";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset CURFILE=
 
  typeset i=1

  __TEMPFILE_CREATED=${__TRUE}

  LogRuntimeInfo "Creating the temporary files  ..."

  while [ ${i} -le ${__NO_OF_TEMPFILES} ]  ; do  
    eval __TEMPFILE${i}="${__TEMPDIR}/${__SCRIPTNAME}.$$.TEMP${i}"
    eval CURFILE="\$__TEMPFILE${i}"

    LogRuntimeInfo "Creating the temporary file \"${CURFILE}\"; the variable is \"\${TEMPFILE${i}}"

    echo >"${CURFILE}" || return $?
   
    eval __LIST_OF_TMP_FILES=\"${__LIST_OF_TMP_FILES} \${__TEMPFILE${i}}\"
    (( i = i +1 ))
  done

  return 0
}

# ======================================


# ======================================

##
## ---------------------------------------
## cleanup
##
## house keeping at program end
##
## usage: [called by the runtime system]
##
## returns: 0
##
## notes:
##  execution order is
##    - call exit routines from ${__EXITROUTINES}
##    - remove files from ${__LIST_OF_TMP_FILES}
##    - umount mount points ${__LIST_OF_TMP_MOUNTS}
##    - remove directories ${__LIST_OF_TMP_DIRS}
##
cleanup() {
  typeset __FUNCTION="cleanup";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset EXIT_ROUTINE=
  typeset OLDPWD="$( pwd )"

  cd /tmp

# reset tty settings if necessary
  if [ "${__STTY_SETTINGS}"x != ""x ] ; then
   stty ${__STTY_SETTINGS}
   __STTY_SETTINGS=""
  fi
 
# call the defined exit routines
  if [ "${__EXITROUTINES}"x !=  ""x ] ; then
    LogRuntimeInfo "Executing the exit routines \"${__EXITROUTINES}\" ..."
    for EXIT_ROUTINE in ${__EXITROUTINES} ; do
      LogRuntimeInfo "Now calling the exit routine \"${EXIT_ROUTINE}\" ..."
      eval ${EXIT_ROUTINE}
    done
  fi

# remove temporary files
  for CURENTRY in ${__LIST_OF_TMP_FILES} ; do
    LogRuntimeInfo "Removing the file \"${CURENTRY}\" ..."
    if [ -f "${CURENTRY}" ] ; then
      rm "${CURENTRY}"
      [ $? -ne 0 ] && LogWarning "Error removing the file \"${CURENTRY}\" "
    fi
  done

# remove temporary mounts
  typeset CURENTRY
  for CURENTRY in ${__LIST_OF_TMP_MOUNTS} ; do
    mount | grep "^${CURENTRY} " 1>/dev/null 2>/dev/null
    if [ $? -eq 0 ] ; then
      LogRuntimeInfo "Umounting \"${CURENTRY}\" ..."
      umount "${CURENTRY}"
      [ $? -ne 0 ] && LogWarning "Error umounting \"${CURENTRY}\" "
    fi
  done

# remove temporary directories
  for CURENTRY in ${__LIST_OF_TMP_DIRS} ; do
    LogRuntimeInfo "Removing the directory \"${CURENTRY}\" ..."
    if [ -d "${CURENTRY}" ] ; then
      rm -r "${CURENTRY}" 2>/dev/null
      [ $? -ne 0 ] && LogWarning "Error removing the directory \"${CURENTRY}\" "
    fi
  done

  [ -d "${OLDPWD}" ] && cd "${OLDPWD}"
 
  return 0
}



##
## ##### defined trap handler (you may change them)
##


## ---------------------------------------
## GENERAL_SIGNAL_HANDLER
##
## general trap handler
##
## usage: called automatically (parameter $1 is the signal number)
##
## returns: -
##
GENERAL_SIGNAL_HANDLER() {
  typeset INTERRUPTED_FUNCTION="${__FUNCTION}"
  typeset __FUNCTION="GENERAL_SIGNAL_HANDLER";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}
  typeset __LINENO=$2

  __TRAP_SIGNAL=$1
 
  LogRuntimeInfo "Trap \"${__TRAP_SIGNAL}\" catched"
     
  [ "${__INCLUDE_SCRIPT_RUNNING}"x != ""x ] && LogMsg "Trap occured inside of the include script \"${__INCLUDE_SCRIPT_RUNNING}\" "
 
  LogRuntimeInfo "Signal ${__TRAP_SIGNAL} received: Line: ${__LINENO} in function: ${INTERRUPTED_FUNCTION}"
 
  case ${__TRAP_SIGNAL} in

    1 )
        LogWarning "HUP signal received"

        InvertSwitch __VERBOSE_MODE
        LogMsg "Switching verbose mode to $( ConvertToYesNo ${__VERBOSE_MODE} )"
        ;;

    2 )
        if [ ${__USER_BREAK_ALLOWED} -eq ${__TRUE} ] ; then
          die 252 "Script aborted by the user via signal BREAK (CTRL-C)"
        else
          LogRuntimeInfo "Break signal (CTRL-C) received and ignored (Break is disabled)"
        fi
        ;;

    3 )
        die 251 "QUIT signal received"
        ;;

   15 )
        die 253 "Script aborted by the external signal TERM"
        ;;

   "ERR" )
        LogMsg "A command ended with an error"
        ;;

   "exit" | 0 )
        if [ "${__EXIT_VIA_DIE}"x != "${__TRUE}"x ] ; then
          LogError "exit signal received."
          LogWarning "You should use the function \"die\" to end the program"
        fi   
        return
        ;;
      
    * ) die 254 "Unknown signal catched: ${__TRAP_SIGNAL}"
        ;;

  esac
}


# ======================================


## ---------------------------------------
## DebugHandler
##
## handler for single step mode
##
## usage: called automatically
##
## returns: the RC of the previous executed command
##
DebugHandler() {
  typeset __FUNCTION="DebugHandler";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "${__DEBUG_MODE}" -ne ${__TRUE} ] && return ${__LAST_RC}

  __STTY_SETTINGS="$( stty -g )"
#  stty erase
 
  typeset __THIS_PID=$$

  typeset -i i=0
  typeset -i j=0

  if [ "${__USE_COLORS}"x = "${__TRUE}"x ] ; then
    typeset __LINE_COLOR="\033[0;36m\033[44m"
    typeset __CUR_LINE_COLOR="\033[0;34m\033[46m"
    typeset __DEBUG_MSG_COLOR="\033[0;31m\033[48m"
    typeset __COLOR_OFF="\033[0;m"  
  else
    typeset __LINE_COLOR=""
    typeset __CUR_LINE_COLOR=""
    typeset __DEBUG_MSG_COLOR=""
    typeset __COLOR_OFF=""
  fi

  COLUMNS=80
  typeset RESIZE_BINARY="$( whence resize )"
  [ "${RESIZE_BINARY}"x = ""x ] && RESIZE_BINARY="/usr/openwin/bin/resize"
  [ -x "${RESIZE_BINARY}" ] && eval $( ${RESIZE_BINARY} )
  (( COLUMNS = $COLUMNS - 1 ))
  eval "typeset -L${COLUMNS} LINE_VAR"
 
#  typeset  -L80 __LINE_VAR=""
  typeset __USERINPUT=""

  set -o emacs
 
  alias __A=$(print "\020")    # up arrow    -> Ctrl-P (previous cmd)
  alias __B=$(print "\016")    # down arrow  -> Ctrl-N (next cmd)
  alias __C=$(print "\006")    # right arrow -> Ctrl-F (move forward 1 char)
  alias __D=$(print "\002")    # left arrow  -> Ctrl-B (move backward 1 char)
  alias __H=$(print "\001")    # home        -> Ctrl-A (go to beginning of line)
  alias __P=$(print "\004")    # delete      -> Ctrl-D (delete char under cursor)
  alias __@=" "
  alias __Q=$(print "\005")    # end         -> Ctrl-E (go to end of line)
  alias __Z=$(print "\017")    # end         -> Ctrl-O (operate)

  export HISTFILE="${__DEBUG_HISTFILE}"
 
# check for the break points
  if [ "${__BREAKPOINT_LINE}"x != "0"x ] ; then
    if [ "${__BREAKPOINT_LINE}" -ge "${__LINENO}" ] ; then
      __LINE_VAR="*** DEBUG: Break point at line ${__LINENO} found"
      print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
      __BREAKPOINT_LINE=0
    else
      return ${__LAST_RC}
    fi
  fi

  if [ "${__STEP_COUNT}"x != "0"x ] ; then
    __STEP_COUNT=$(( __STEP_COUNT - 1 ))
    if [  "${__STEP_COUNT}"x = "0"x  ] ; then
      __LINE_VAR="*** DEBUG: Break point at line ${__LINENO} found"
      print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
    else
      return ${__LAST_RC}
    fi
  fi


# read the script into an array (only once!)
  if [ ${__SCRIPT_ARRAY[0]} = 0 ] ; then
    typeset oIFS=$IFS
    IFS="\n"

    i=1

    while read -r __SCRIPT_ARRAY[$i] ; do
      i=$(( i+1 ))
    done <$0

    __SCRIPT_ARRAY[0]=$i

    IFS=$oIFS
  fi

# define the variables for the output

  i=${__SCRIPT_ARRAY[0]}
  eval "typeset -R${#i} NUM_VAR" 
  j=$(( ${COLUMNS} - ${#i} -1 ))
#  eval "typeset -L${j} __SRCLINE_VAR" 
  eval "typeset -L${COLUMNS} __SRCLINE_VAR"
 
  if [ "${__TRACE_COUNT}"x != "0"x ] ; then
    __SRCLINE_VAR="${NUM_VAR}>>> ${__SCRIPT_ARRAY[${__LINENO}]}"
    print -u2 "${__CUR_LINE_COLOR}${__SRCLINE_VAR}"
    __TRACE_COUNT=$(( ${__TRACE_COUNT}-1 ))
    print "${__COLOR_OFF}"
    return ${__LAST_RC}
  fi

# write the script to a file 
#  i=1
#  while [ i -lt ${__SCRIPT_ARRAY[0]} ] ; do
#     echo "$i ${__SCRIPT_ARRAY[$i]}" >>./test.out
#     i=$(( i+1 ))
#  done
   
  __LINE_VAR=""  
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  __LINE_VAR="*** DEBUG: Executed line: ${__LINENO}"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
  __LINE_VAR="*** DEBUG: Line Context:"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  [ ${__LINENO} -gt 5 ] && i=$(( ${__LINENO}-5 )) || i=1
  typeset CUR_SRC_WIN_START=$i
  j=$(( ${__LINENO}+5 ))
  [ ${j} -gt ${__SCRIPT_ARRAY[0]} ] && j=${__SCRIPT_ARRAY[0]}

# write the context of the line just executed  
  while [ i -lt j ] ; do
    NUM_VAR=$i
    if [ $i -eq ${__LINENO} ] ; then
      __SRCLINE_VAR="${NUM_VAR}>>> ${__SCRIPT_ARRAY[$i]}"
      print -u2 "${__CUR_LINE_COLOR}${__SRCLINE_VAR}${__COLOR_OFF} "
    else
      __SRCLINE_VAR="${NUM_VAR}    ${__SCRIPT_ARRAY[$i]}"
      print -u2 "${__LINE_COLOR}${__SRCLINE_VAR}${__COLOR_OFF} "
    fi
      i=$(( i+1 ))
  done  
  print "${__COLOR_OFF}"
 
# read the user input
#
  __LINE_VAR="*** DEBUG: \$\$ is ${__THIS_PID}; \$? is ${__LAST_RC}; \$! is ${__LAST_BG_RC}"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
  __LINE_VAR="*** DEBUG: Enter a command to execute or <enter> to execute the next command:"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  while [ 1 = 1 ] ; do
    echo $COLUMNS
    echo $LINE
    print -u2 -n  "${__DEBUG_MSG_COLOR}DEBUG>>> "
    read -s __USERINPUT __USERPARMS __USERVALUE __USERVALUE2
 
    case ${__USERINPUT} in

      "help" | "?" ) __LINE_VAR="*** DEBUG:Known commands"
           print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
cat 1>&2 <<EOT

  help                      - print this text
  trace count               - execute count lines
  trace off                 - turn single mode off
  trace at lineNo           - suspend single step until line linNo
  trace not lineNumber      - suspend single step for lineNumber statements
  show lineNo [count]       - show count (def.: 10) lines after line lineNo
  exit [returncode]         - exit the program with RC returnCode (def.: 1)
  <return>                  - execute next statement (single step)
  everything else           - execute the command

EOT
           ;;
  
  
      "" ) break
           ;;
          
      "trace"  ) :
          case ${__USERPARMS}  in

            "off" )
              __LINE_VAR="*** DEBUG: Turning single step mode off"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __DEBUG_MODE=${__FALSE}
              break
              ;;
     
            "at" )
              if [ "${__USERVALUE}"x = ""x ] ; then
                __LINE_VAR="*** DEBUG: value missing"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi

              isNumber "${__USERVALUE}" 2>/dev/null
              if [ $? -ne 0 ] ; then
                __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi        

              __LINE_VAR="*** DEBUG: Suspending single step until line ${__USERVALUE}"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __BREAKPOINT_LINE=${__USERVALUE}     
              break
              ;;

            "not" )
              if [ "${__USERVALUE}"x = ""x ] ; then
                __LINE_VAR="*** DEBUG: value missing"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi

              isNumber "${__USERVALUE}" 2>/dev/null
              if [ $? -ne 0 ] ; then
                __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi        

              __LINE_VAR="*** DEBUG: Suspending single step for the next ${__USERVALUE} statements"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __STEP_COUNT=${__USERVALUE}     
              break
              ;;


            * )
              isNumber "${__USERPARMS}" 2>/dev/null
              if [ $? -eq 0 ] ; then
                __TRACE_COUNT=${__USERPARMS}
                __LINE_VAR="*** DEBUG: Executing \"${__USERPARMS}\" lines"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                break
              else
                __LINE_VAR="*** DEBUG: unknown trace option \"${__USERPARMS}\" "
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"   
              fi
              ;;
     
          esac
          ;;  

      "show" )     
           [ "${__USERPARMS}"x = ""x ] && __USERPARMS=${CUR_SRC_WIN_START}

           isNumber "${__USERPARMS}" 2>/dev/null
           if [ $? -ne 0 ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is not a number"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
             continue
           fi        

           if [ "${__USERPARMS}" -lt 1 ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is out of range"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
             continue
           fi        

           if [ "${__USERPARMS}" -gt ${__SCRIPT_ARRAY[0]} ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is out of range (last line is ${__SCRIPT_ARRAY[0]})"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"   
             continue
           fi

           i=${__USERPARMS}

           if [ "${__USERVALUE}"x != ""x ] ; then
             isNumber "${__USERVALUE}" 2>/dev/null
             if [ $? -ne 0 ] ; then
               __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
               print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
               continue
             fi        
             j=$(( ${i}+ ${__USERVALUE} -1 ))
           else
             j=$(( ${i}+9 ))  
           fi

           [ ${j} -gt ${__SCRIPT_ARRAY[0]} ] && j=${__SCRIPT_ARRAY[0]}

           while [ i -le j ] ; do
             NUM_VAR=$i
             if [ $i -eq ${__LINENO} ] ; then
               __SRCLINE_VAR=">>> ${__SCRIPT_ARRAY[$i]}"
               print -u2 "${__CUR_LINE_COLOR}${NUM_VAR} ${__SRCLINE_VAR}"
             else
               __SRCLINE_VAR="    ${__SCRIPT_ARRAY[$i]}"
               print -u2 "${__LINE_COLOR}${NUM_VAR} ${__SRCLINE_VAR}"
             fi
             i=$(( i+1 ))
           done     
    
           ;;
  
      "exit" | "quit" )  :
           print "${__COLOR_OFF}"
           [ "${__USERPARMS}"x = ""x ] && die 252 "Program aborted by the user"
           die ${__USERPARMS}
           ;;

      * ) executeCommand "${__USERINPUT}" "${__USERPARMS}" "${__USERVALUE}" "${__USERVALUE2}"
            ;;
    esac
  done
  print "${__COLOR_OFF}"

  return ${__LAST_RC}
}



## ---------------------------------------
## InitScript
##
## init the script runtime
##
## usage: [called by the runtime system]
##
## returns: 0
##
InitScript() {   
  typeset __FUNCTION="InitScript";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

# use a temporary log file until we know the real log file
  __TEMPFILE_CREATED=${__FALSE}
  __MAIN_LOGFILE=${__LOGFILE}
 
  __LOGFILE="/tmp/${__SCRIPTNAME}.$$.TEMP"
  echo >${__LOGFILE}

  LogHeader "${__SCRIPTNAME} started on $( date ) "

  LogRuntimeInfo "Script template used is \"${__SCRIPT_TEMPLATE_VERSION}\" ."

  __WRITE_CONFIG_AND_EXIT=${__FALSE}
 
# init the variables
  eval "${__CONFIG_PARAMETER}"

# read the config file
  ReadConfigFile

  return 0
}


## ---------------------------------------
## SetEnvironment
##
## set and check the environment
##
## usage: [called by the runtime system]
##
## returns: 0
##
SetEnvironment() {
  typeset __FUNCTION="SetEnvironment";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

# copy the temporary log file to the real log file

  if [ "${NEW_LOGFILE}"x = "nul"x ] ; then
    LogHeader "Running without a log file"
    __MAIN_LOGFILE=""
# delete the temporary logfile  
    rm "${__LOGFILE}" 2>/dev/null
    __LOGFILE=""
  else
    [ "${NEW_LOGFILE}"x != ""x ] && __MAIN_LOGFILE="${NEW_LOGFILE}"
    LogRuntimeInfo "Initializing the log file\"${__MAIN_LOGFILE}\" "

    touch "${__MAIN_LOGFILE}" 2>/dev/null
    cat "${__LOGFILE}" >>${__MAIN_LOGFILE} 2>/dev/null
    if [ $? -ne 0 ]   ; then
      LogWarning "Error writing to the logfile \"${__MAIN_LOGFILE}\"."
      LogWarning "Using the log file \"${__LOGFILE}\" "
    else
      rm "${__LOGFILE}" 2>/dev/null
      __LOGFILE="${__MAIN_LOGFILE}"
    fi
    LogHeader "Using the log file \"${__LOGFILE}\" "
  fi

  LogRuntimeInfo "Parameter before getopt processing are: \"${THIS_PARAMETER}\" "
  LogRuntimeInfo "Not processed parameter after getopt processing are: \"${NOT_PROCESSED_PARAMETER}\" "

  if [ "${__REQUIRED_OS}"x != ""x ] ; then
    pos " ${__OS} " " ${__REQUIRED_OS} " && \
      die 238 "This script can not run on this operating system (${__OS}); known Operating systems are \"${__REQUIRED_OS}\""
  fi

  if [ "${__REQUIRED_OS_VERSION}"x != ""x ] ; then

    LogRuntimeInfo "Curent OS version is \"${__OS_VERSION}\"; required OS version is \"${__REQUIRED_OS_VERSION}\""

    __OS_VERSION_OKAY=${__TRUE}
   
    __CUR_MAJOR_VER="${__OS_VERSION%.*}"
    __CUR_MINOR_VER="${__OS_VERSION#*.}"

    __REQ_MAJOR_VER="${__REQUIRED_OS_VERSION%.*}"
    __REQ_MINOR_VER="${__REQUIRED_OS_VERSION#*.}"

    [ "${__CUR_MAJOR_VER}" -lt "${__REQ_MAJOR_VER}" ] && __OS_VERSION_OKAY=${__FALSE}
    [ "${__CUR_MAJOR_VER}" -eq "${__REQ_MAJOR_VER}"  -a "${__CUR_MINOR_VER}" -lt "${__REQ_MINOR_VER}" ] && __OS_VERSION_OKAY=${__FALSE}

     [ ${__OS_VERSION_OKAY} = ${__FALSE} ] && die 248 "Unsupported OS Version: ${__OS_VERSION}; necessary OS version is ${__REQUIRED_OS_VERSION}"

  fi

  if [ "${__REQUIRED_MACHINE_PLATFORM}"x != ""x ] ; then
    pos " ${__MACHINE_PLATFORM} " " ${__REQUIRED_MACHINE_PLATFORM} " && \
      die 245 "This script can not run on this platform (${__MACHINE_PLATFORM}); necessary platforms are \"${__REQUIRED_MACHINE_PLATFORM}\""
  fi

  if [ "${__REQUIRED_MACHINE_CLASS}"x != ""x ] ; then
    pos " ${__MACHINE_CLASS} " " ${__REQUIRED_MACHINE_CLASS} " && \
      die 244 "This script can not run on this machine class (${__MACHINE_CLASS}); necessary machine classes are \"${__REQUIRED_MACHINE_CLASS}\""
  fi

  if [ "${__REQUIRED_MACHINE_ARC}"x != ""x ] ; then
    pos " ${__MACHINE_ARC} " " ${__REQUIRED_MACHINE_ARC} " && \
      die 243 "This script can not run on this machine architecture (${__MACHINE_ARC}); necessary machine classes are \"${__REQUIRED_MACHINE_ARC}\""
  fi

  if  [ "${__ZONENAME}"x != ""x -a "${__OS}"x = "SunOS"x ] ; then
    case "${__REQUIRED_ZONE}" in

     "global" )
       [ "${__ZONENAME}"x != "global"x ] && die 239 "This script must run in the global zone; the current zone is \"${__ZONENAME}\""
       ;;

     "non-global" | "local" )
       [ "${__ZONENAME}"x = "global"x ] && die 239 "This script can not run in the global zone"
       ;;

     "" ) :
       ;;

     * )
       [ "${__ZONENAME}"x = "global"x ] && die 239 "This script must run in the zone \"${__REQUIRED_ZONE}\"; the current zone is \"${__ZONENAME}\" "
       ;;

    esac

  fi

  if [ ${__MUST_BE_ROOT} -eq ${__TRUE} ] ; then 
    UserIsRoot || die 249 "You must be root to execute this script"
  fi

  if [ "${__REQUIRED_USERID}"x != ""x ] ; then
    pos " ${__USERID} "  " ${__REQUIRED_USERID} " && \
      die 242 "This script can only be executed by one of the users: ${__REQUIRED_USERID}"
  fi

  if [ ${__ONLY_ONCE} -eq ${__TRUE} ] ; then
    CreateLockFile
    if [ $? -ne 0 ] ; then
      cat >&2  <<EOF

  ERROR:

  Either another instance of this script is already running
  or the last execution of this script crashes.
  In the first case wait until the other instance ends;
  in the second case delete the lock file
 
      ${__LOCKFILE}

  manually and restart the script.

EOF

      die 250
    fi

# remove the lock file at program end
    __EXITROUTINES="${__EXITROUTINES} RemoveLockFile"   
  fi

# __ABSOLUTE_SCRIPTDIR real absolute directory (no link)
  GetProgramDirectory "$0" __ABSOLUTE_SCRIPTDIR

# create temporary files
  CreateTemporaryFiles

# check for the parameter -C
  if [   "${__WRITE_CONFIG_AND_EXIT}" = ${__TRUE} ] ; then
    NEW_CONFIG_FILE="${__CONFIG_FILE}"
    LogMsg "Creating the config file \"${NEW_CONFIG_FILE}\" ..."
    WriteConfigFile "${NEW_CONFIG_FILE}"
    [ $? -ne 0 ] && die 246 "Error writing the config file \"${NEW_CONFIG_FILE}\""
    die 0 "Configfile \"${NEW_CONFIG_FILE}\" written successfully."   
  fi

}


##
## ##### defined sub routines
##

## --------------------------------------
## CheckParameterCount
##
## check the number of parameters for a function
##
## usage: CheckParameterCount parametercount "$@"
##
## returns:  ${__TRUE} - the no of parameter is ok
##           ${__FALSE} - the no of parameter is not ok
##         
##
CheckParameterCount(){
  typeset __CALLED_BY="${__FUNCTION}"
  
  typeset __FUNCTION="CheckParameterCount";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=${__FALSE}

  typeset __PARAMETER_COUNT=$1
  shift
 
  if [ $# -eq ${__PARAMETER_COUNT} ] ; then
    THISRC=${__TRUE}
  else
    LogError "CheckParameterCount - Function \"${__CALLED_BY}\" called with $# parameters but the function expects ${__PARAMETER_COUNT} parameter"
    if [ $# -ne 0 ] ; then
      LogError "The parameter are:"
      typeset i=1
      while [ $# -ne 0 ] ; do
        LogError "\$$i : \"$1\" "
        (( i = i + 1 ))
        shift
      done
    fi
  fi

  return ${THISRC}
}


## ---------------------------------------
## ShowShortUsage
##
## print the (short) usage help
##
## usage: ShowShortUsage
##
## returns: 0
##
ShowShortUsage() {
  typeset __FUNCTION="ShowShortUsage";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "__SHORT_USAGE_HELP=\"${__SHORT_USAGE_HELP}\""

cat <<EOT
  ${__SCRIPTNAME} ${__SCRIPT_VERSION} - ${__SHORT_DESC}

  Usage: ${__SCRIPTNAME} [-T] [-v|+v] [-q|+q] [-h] [-l logfile|+l] [-y|+y] [-n|+n]
                         [-D|+D] [-a|+a] [-O|+O] [-f|+f] [-C] [-H] [-S n] [-V]
${__SHORT_USAGE_HELP}
 
EOT

  return 0
}


## ---------------------------------------
## ShowUsage
##
## print the (long) usage help
##
## usage: ShowUsage
##
## returns: 0
##
ShowUsage() {
  typeset __FUNCTION="ShowUsage";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "__LONG_USAGE_HELP=\"${__LONG_USAGE_HELP}\""

  ShowShortUsage
cat <<EOT

 Note: Use -{switch} or --{longswitch} to turn an option on;
       use +{switch} or ++{longswitch} to turn an option off

       The long format of the parameter (--parameter/++parameter) is not supported by all ksh implementations
      
      
    Parameter:

      -v|+v - turn verbose mode on/off; current value: $( ConvertToYesNo "${__VERBOSE_MODE}" )
              Long format: --verbose / ++verbose
      -q|+q - turn quiet mode on/off; current value: $( ConvertToYesNo "${__QUIET_MODE}" )
              Long format: --quiet / ++quiet
      -h    - show usage
              Long format: --help
      -l    - set the logfile
              current value: ${NEW_LOGFILE:=${__DEF_LOGFILE}}
              Long format: --logfile     
      +l    - do not write a logfile
              Long format: ++logfile
      -y|+y - assume yes to all questions or not
              Long format: --yes / ++yes
      -n|+n - assume no to all questions or not
              Long format: --no /++no
      -D|+D - run main in single step mode (and turn colors on); current value: $( ConvertToYesNo "${__DEBUG_MODE}" )
              Long format: --debug / ++debug
      -a|+a - turn colors on/off; current value: $( ConvertToYesNo "${__USE_COLORS}" )
              Long format: --color / ++color
      -O|+O - overwrite existing files or not; current value: $( ConvertToYesNo "${__OVERWRITE_MODE}" )
              Long format: --overwrite / ++overwrite
      -f|+f - force; do it anyway; current value: $( ConvertToYesNo "${__FORCE}" )
              Long format: --force / ++force
       -C   - write a default config file in the current directory and exit
              Long format: --writeconfigfile
      -S n  - print error/warning summaries:
              n = 0 no summarys, 1 = print error msgs,
              2 = print warning msgs, 3 = print error and warning mgs
              Current value: ${__PRINT_SUMMARIES}
              Long format: --summaries
      -H    - write extended usage to STDERR and exit
              Long format: --doc
      -V    - write version number to STDOUT and exit
              Long format: --version
      -T    - append STDOUT and STDERR to the file "${__TEE_OUTPUT_FILE}"
              Note: This parameter must be the FIRST parameter if used!
              Long format: --tee
${__LONG_USAGE_HELP}

Used environment variables:
$( echo "${__USED_ENVIRONMENT_VARIABLES}" | tr "#" " " )

EOT

  return 0
}

# -----------------------------------------------------------------------------

## --------------------------------------
## PrintRuntimeVariables
##
## print the values of the runtime variables
##
## usage: PrintRuntimeVariables
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##
##
PrintRuntimeVariables(){
  typeset __FUNCTION="PrintRuntimeVariables";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset CURVAR CURVALUE

  typeset __RUNTIME_VARIABLES="
__SAVE_LANG
__SCRIPTNAME
__REAL_SCRIPTDIR
__CONFIG_FILE
__HOSTNAME
__NODENAME
__OS
__OS_VERSION
__ZONENAME
__OS_RELEASE
__MACHINE_CLASS
__START_DIR
__MACHINE_PLATFORM
__MACHINE_SUBTYPE
__MACHINE_ARC
__LOGFILE
__LOGIN_USERID
__USERID
__RUNLEVEL
"

# init the return code
  THISRC=${__INVALID_USAGE}

# check the parameter count
  CheckParameterCount 0 "$@" || die 240 "Internal error detected"

  if [ $# -eq 0 ] ; then
    THISRC=${_TRUE}

    for CURVAR in ${__RUNTIME_VARIABLES} ; do
      eval CURVALUE="\$${CURVAR}"
      LogMsg "Variable \"${CURVAR}\" is \"${CURVALUE}\" "
    done
  fi

  return ${THISRC}
}

## --------------------------------------
## FormatCommandOutput
##
## format the output of a command for html pages
##
## usage: FormatCommandOutput command {parameter}
##
## returns:  the return code of the command
##          
##           The text for the html page is written to STDOUT
##         
##
FormatCommandOutput(){
  typeset __FUNCTION="FormatCommandOutput";    ${__DEBUG_CODE}

  typeset CMDOUTPUT=""
  typeset CUR_CMDS=""
  typeset LINE=""

  THISRC=0

  while [ 0 = 0 ] ; do
 
#    whence $1 >/dev/null
#    if [ $? -ne 0 ] ; then
#      PrintErrorMsg "Can not execute \"$*\""
#      THISRC=255
#      break
#    fi

#    if [ "$1"x = "cat"x ] ; then
#      if [ ! -r "$2" ] ; then
#        PrintErrorMsg "The file \"$2\" does not exist"
#        THISRC=255
#	break
#      fi
#    fi     

#    if [ "$1"x = "tail"x ] ; then
#      if [ ! -r "$3" ] ; then
#        PrintErrorMsg "The file \"$3\" does not exist"
#        PrintErrorMsg "The file \"$3\" does not exist"
#        THISRC=255
#	break
#      fi
#    fi     

    if [ ${__VERBOSE_MODE} = ${__TRUE} ] ; then
      CUR_CMDS="$*"
      CMDOUTPUT="### Command: \"$*\"
"
    else
      CUR_CMDS="$*"
      CMDOUTPUT=""
    fi
    
    CMDOUTPUT="${CMDOUTPUT}
$( eval ${CUR_CMDS} 2>&1 ) 
"

   
    CMD_RC=$?
    if [ ${CMD_RC} != 0 ] ; then
      PrintErrorMsg "The RC of the command \"$*\" is ${CMD_RC}"
      echo "<br>"
      THISRC=255
    fi     

    echo "${CMDOUTPUT}" | sed "s/ /\&nbsp;/g" | sed "s/	/\&nbsp;\&nbsp;\&nbsp;\&nbsp;/g" | while read LINE ; do
      echo "<samp>${LINE}<br></samp>"
    done   
    break
  done

  return ${THISRC}
}

## --------------------------------------
## YourRoutine
##
## template for a user defined function
##
## usage: YourRoutine
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##         
##
YourRoutine(){
  typeset __FUNCTION="YourRoutine";    ${__DEBUG_CODE}

# init the return code
  THISRC=${__INVALID_USAGE}

# check the parameter count
  CheckParameterCount 0 "$@" || die 240 "Internal error detected"
 
  if [ $# -eq 0 ] ; then
    THISRC=${__FALSE}

# add code here

  fi

  die 0 "test exit"

  return ${THISRC}
}



## --------------------------------------
## PrintSeparator
##
## print a horizontal line and previous/next link
##
## usage: PrintSeparator [nextsection]
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##         
##
PrintSeparator(){
  typeset __FUNCTION="PrintSeparator";    ${__DEBUG_CODE}
 
  typeset THISRC=${__TRUE}

  typeset LINK_LINE="${SEPARATOR_LINE}<div style=\"text-align: right;\">"

  if [ $# -ne 0 ] ; then
    LINK_LINE="${LINK_LINE}<a name=\"$1_topic\"></a>"
    shift
  fi

  if [ $# -ne 0 ] ; then
    LINK_LINE="${LINK_LINE}<a href="#${1}_topic">&lt;previous&gt;&nbsp;</a>"
    shift
  fi

  LINK_LINE="${LINK_LINE}&nbsp;<a href="#top">&lt;top&gt;</a>"

  if [ $# -ne 0 ] ; then
    LINK_LINE="${LINK_LINE}&nbsp;<a href="#${1}_topic">&lt;next&gt;</a>"
    shift
  fi

  LINK_LINE="${LINK_LINE}</div>${SEPARATOR_LINE}"

  echo "${LINK_LINE}" 

  return ${THISRC}
}

## --------------------------------------
## PrintErrorMsg
##
## print an error msg and explanation to STDOUT
##
## usage: PrintErrorMsg [errormsg] {explanation}
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##         
##
PrintErrorMsg(){
  typeset __FUNCTION="PrintErrorMsg";    ${__DEBUG_CODE}

  typeset i=0

# init the return code
  THISRC=${__TRUE}

  echo "<br><strong>"

  if [ $# -gt 0 ] ; then
    echo "ERROR: $1!<br>"
    shift
  fi   

  while [ $# -ne 0 ] ; do
    echo "      $1<br>"
    shift
  done   
  echo "</strong>"

  return ${THISRC}
}


## --------------------------------------
## YourRoutine
##
## template for a user defined function
##
## usage: YourRoutine
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##         
##
YourRoutine(){
  typeset __FUNCTION="YourRoutine";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}
  echo $LINENO
# init the return code
  THISRC=${__INVALID_USAGE}

# check the parameter count
  CheckParameterCount 0 "$@" || die 240 "Internal error detected"

  if [ $# -eq 0 ] ; then
    THISRC=${__FALSE}

# add code here

  fi

  die 0 "test exit"

  return ${THISRC}
}

# -----------------------------------------------------------------------------
# main:
#

# trace main routine
#
# set -x

# trace also all function defined before this line (!)
#
# typeset -ft $( typeset +f )

# install trap handler
  __settrap

  InitScript

# ??? init variables with the defaults
#
# format var=${DEFAULT_var}
#

# to process all variables beginning with DEFAULT_ use

  for CURVAR in $( set | grep "^DEFAULT_"  | cut -f1 -d"=" ) ; do
    P1="${CURVAR%%=*}"
    P2="${P1#DEFAULT_*}"

# for debugging
#    push_and_set __VERBOSE_MODE ${__TRUE}
#    push_and_set __VERBOSE_LEVEL ${__RT_VERBOSE_LEVEL}
#    LogInfo 0 "Setting variable $P2= \"$( eval "echo \"\$$P1\"")\" "
#    pop __VERBOSE_MODE
#    pop __VERBOSE_LEVEL

    eval "$P2="\"\$$P1\"""
  
  done

# --- variables for the cleanup routine:
#
# add mounts that should be automatically be unmounted at script end to this variable
#
#  __LIST_OF_TMP_MOUNTS="${__LIST_OF_TMP_MOUNTS} "

# add directories that should be automatically removed at script end to this variable
#
#  __LIST_OF_TMP_DIRS="${__LIST_OF_TMP_DIRS} "

# add files that should be automatically removed at script end to this variable
#  __LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} "

# add functions that should be called automatically at program end to this variable
#
#  __EXITROUTINES="${__EXITROUTINES} "   


# variables used by getops:
#    OPTIND = index of the current argument
#    OPTARG = current function character
#

  INVALID_PARAMETER_FOUND=${__FALSE}

  __PRINT_USAGE=${__FALSE}
  CUR_SWITCH=""
  OPTARG=""

  [ "${__OS}"x = "Linux" ] &&  GETOPT_COMPATIBLE="0"
  while getopts ":y(yes)n(no)v(verbose)q(quiet)h(help)H(doc)D(debug)f(force)l:(logfile)a(color)O(overwrite)S:(summaries)C(writeconfigfile)V(version)T(tee)c:(command)i:(other_configfile)o:(output_file)N:(logfile_linecount)" CUR_SWITCH  ; do

# for debugging only
    if [ 0 = 1 ] ; then
      echo "CUR_SWITCH is $CUR_SWITCH"
      echo "OPTIND = $OPTIND"
      echo "OPTARG = $OPTARG"
      echo "\$* is \"$*\" "
    fi

    if [ "${CUR_SWITCH}" = ":" ] ; then
      CUR_SWITCH=${OPTARG}
      OPTARG=""
    fi

    case ${CUR_SWITCH} in

       "C" ) __WRITE_CONFIG_AND_EXIT=${__TRUE} ;;

      "+D" ) __DEBUG_MODE=${__FALSE}  ;;
     
       "D" ) __DEBUG_MODE=${__TRUE} ; __USE_COLORS=${__TRUE} ;;

      "+v" ) __VERBOSE_MODE=${__FALSE}  ;;

       "v" ) __VERBOSE_MODE=${__TRUE} ; (( __VERBOSE_LEVEL=__VERBOSE_LEVEL+1 )) ;;

      "+q" ) __QUIET_MODE=${__FALSE} ;;

       "q" ) __QUIET_MODE=${__TRUE} ;;

      "+a" ) __USE_COLORS=${__FALSE} ;;

      "a"  ) __USE_COLORS=${__TRUE} ;;

      "+O" ) __OVERWRITE_MODE=${__FALSE} ;;

       "O" ) __OVERWRITE_MODE=${__TRUE} ;;

       "f" ) __FORCE=${__TRUE} ;;

      "+f" ) __FORCE=${__FALSE} ;;

       "l" ) NEW_LOGFILE="${OPTARG:=nul}" ;;

      "+l" ) NEW_LOGFILE="nul" ;;

      "+h" ) __VERBOSE_MODE=${__TRUE}
             __PRINT_USAGE=${__TRUE}
             ;;

       "h" ) __PRINT_USAGE=${__TRUE} ;;

       "T" ) : # parameter already processed
             ;;

       "H" )

echo " -----------------------------------------------------------------------------------------------------" >&2
echo "                         ${__SCRIPTNAME} ${__SCRIPT_TEMPLATE_VERSION} ">&2
echo "                                Documentation" >&2
echo " -----------------------------------------------------------------------------------------------------" >&2

             grep "^##" "$0" | cut -c3-100 1>&2 ; die 0 ;;


       "V" ) LogMsg "Script version: ${__SCRIPT_VERSION}"
             if [ ${__VERBOSE_MODE} = ${__TRUE} ] ; then
               LogMsg "Script template version: ${__SCRIPT_TEMPLATE_VERSION}"
             fi
             die 0 ;;


      "+y" ) __USER_RESPONSE_IS="" ;;

       "y" ) __USER_RESPONSE_IS="y" ;;

      "+n" ) __USER_RESPONSE_IS="" ;;

       "n" ) __USER_RESPONSE_IS="n" ;;

       "S" ) case ${OPTARG} in

                0 | 1 | 2 | 3 ) __PRINT_SUMMARIES=${OPTARG}
                                    ;;

                * )  LogError "Unknown value for -S found found: \"${OPTARG}\""
                      INVALID_PARAMETER_FOUND=${__TRUE}
                      ;;
                esac
                ;;


        "c" )
          (( i = ${COMMAND_ARRAY[0]}+1 ))
          COMMAND_ARRAY[$i]="${OPTARG}"
          COMMAND_ARRAY[0]=$i
          ;;

        "i" ) (( i = ${XEN_CONFIG_FILE_ARRAY[0]}+1 ))
          XEN_CONFIG_FILE_ARRAY[$i]="${OPTARG}"
          XEN_CONFIG_FILE_ARRAY[0]=$i
          ;;

        "o" ) OUTPUT_FILE="${OPTARG}"
           ;;

        "N" ) LOGFILE_LINE_COUNT="${OPTARG}"
          ;;

    
        \? ) LogError "Unknown parameter found: \"${OPTARG}\" "
             INVALID_PARAMETER_FOUND=${__TRUE}
             break
          ;;

         * ) LogError "Unknown parameter found: \"${CUR_SWITCH}\""
             INVALID_PARAMETER_FOUND=${__TRUE}
             break ;;            

    esac
  done

  case ${__PRINT_SUMMARIES} in
     0 )  __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE}
           __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
           ;;

    1 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE}
           __PRINT_LIST_OF_ERROR_MSGS=${__TRUE}
           ;;

    2 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__TRUE}
           __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
           ;;

    3 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__TRUE}
           __PRINT_LIST_OF_ERROR_MSGS=${__TRUE}
           ;;

    * ) : this should never happen but who knows ...
          __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE}
          __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
  esac

  LogRuntimeInfo "Parameter after processing the default parameter are: " "\"$*\" "


  if [ ${__PRINT_USAGE} = ${__TRUE} ] ; then
    if [ ${__VERBOSE_MODE} -eq ${__TRUE} ] ; then
      ShowUsage
      __VERBOSE_MODE=${__FALSE}
    else
      ShowShortUsage
      LogMsg "Use \"-v -h\" or \"+h\" for a long help text"
    fi
    die 1 ;  
  fi

  shift $(( OPTIND - 1 ))

  NOT_PROCESSED_PARAMETER="$*"

  LogRuntimeInfo "Not processed parameter: \"${NOT_PROCESSED_PARAMETER}\""


#
# set INVALID_PARAMETER_FOUND to ${__TRUE} if the script
# should abort due to an invalid parameter
#
  if [ "${NOT_PROCESSED_PARAMETER}"x != ""x ] ; then
    LogError "Unknown parameter: \"${NOT_PROCESSED_PARAMETER}\" "
    INVALID_PARAMETER_FOUND=${__TRUE}
  fi
 
  isNumber "${LOGFILE_LINE_COUNT}"
  if [ $? != ${__TRUE} ] ; then
    LogError "The value for the parameter -N is not a number"
    INVALID_PARAMETER_FOUND=${__TRUE}
  fi

# exit the program if there are one or more invalid parameter
#
  if [ ${INVALID_PARAMETER_FOUND} -eq ${__TRUE} ] ; then
    LogError "One or more invalid parameters found"
    ShowShortUsage
    die 2
  fi

  SetEnvironment

  if [ "${__DEBUG_MODE}" -eq ${__TRUE} ] ; then
     __LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} ${__DEBUG_HISTFILE}"

    trap "__LAST_RC=\$?; __LAST_BG_RC=\$!; __LINENO=\$LINENO; DebugHandler"  DEBUG
:
    echo "INFO: Starting single step mode - works only for the main routine!"
  fi

# restore the language setting
#
  LANG=${__SAVE_LANG}
  export LANG

  LogMsg "The ouptut file is \"${OUTPUT_FILE}\""
  BackupFileIfNecessary "${OUTPUT_FILE}"

  touch "${OUTPUT_FILE}" || die 107 "Can not create the file \"${OUTPUT_FILE}\""

  EXPLORER_DATA_HOST="$( uname -n)"
  EXPLORER_DATA_DATE="$( date )"

# check if we're running in a Dom0
#
  XEN_STATUS=""

  if [ "$( uname -i )"x = "i86xpv"x ] ; then
    if [ "$(  cat /dev/xen/domcaps 2>/dev/null )"x = "control_d"x ] ; then
      XEN_STATUS="dom0"
    else
      XEN_STATUS="domU"
    fi
  else
    XEN_STATUS="none"
  fi


# -----------------------------------------------------------------------------------------------------------

  case ${XEN_STATUS} in
    "dom0" )
      XEN_STATUS_MSG="Running in a Dom0"
      LogMsg "${XEN_STATUS_MSG}"
      ;;

    "domU" )
      XEN_STATUS_MSG="Running in a DomU"
      LogMsg "${XEN_STATUS_MSG}"
      ;;

    "none" )
      XEN_STATUS_MSG="Running on bare metal (no xen at all)"
      LogMsg "${XEN_STATUS_MSG}"
      ;;

    * )
      XEN_STATUS_MSG="Running on $( uname -i ) (no xen)"
      LogMsg "${XEN_STATUS_MSG}"
    ;;

  esac

# ------------------------------------------------------------------------------------------------------------
# collect the data

# OS related information

  LogMsg "Collecting OS related information ..."
  EXPLORER_DATA_UNAME_A="$( FormatCommandOutput uname -a )"

  EXPLORER_DATA_ISA_INFO_V="$( FormatCommandOutput isainfo -v )"
  EXPLORER_DATA_PRTDIAG="$( FormatCommandOutput prtdiag -v )"
  EXPLORER_DATA_PRTCONF="$( FormatCommandOutput prtconf )"
  
  EXPLORER_DATA_RELEASE="$( FormatCommandOutput cat /etc/release )"
  EXPLORER_DATA_INSTALL_CLUSTER="$( FormatCommandOutput cat /var/sadm/system/admin/CLUSTER )"

  GRUB_MENU_FILE="$( echo $( set -- $( bootadm list-menu | grep "GRUB" ) ; eval echo \$$#  ) )"
  EXPLORER_DATA_GRUBMENU="$( FormatCommandOutput egrep -v '^#\|^$'  ${GRUB_MENU_FILE} )"

  EXPLORER_DATA_ETCSYSTEM="$( FormatCommandOutput grep ' -v "^*" /etc/system | grep -v "^$" ; /bin/true ' )"
  
# THISDATA=$( grep -v "^*" /etc/system | grep -v "^$"  )
# if [ "${THISDATA}"x != ""x ] ; then
#   EXPLORER_DATA_ETCSYSTEM="$( FormatCommandOutput grep ' -v "^*" /etc/system | grep -v "^$" ' )"
#  else
#   EXPLORER_DATA_ETCSYSTEM="no entries in /etc/system"
#  fi   

  EXPLORER_DATA_MODINFO="$( FormatCommandOutput modinfo )"

# patch list
  EXPLORER_PATCH_LIST="$( FormatCommandOutput showrev '-p | cut -f2 -d " "' )"

# network configuration

  LogMsg "Collecting network related information ..."
  EXPLORER_DATA_NETWORK_CONFIG="$( FormatCommandOutput 'dladm show-dev ; echo ""; dladm show-link ; echo ""; ifconfig -a' )"
  EXPLORER_DATA_NAMERESOLUTION_CONFIG="$( FormatCommandOutput egrep -v '^#\|^$' /etc/nsswitch.conf )"
  EXPLORER_DATA_ROUTING_CONFIG="$( FormatCommandOutput netstat -rn )"

# processes and services
  LogMsg "Collecting process related information ..."

  if [ -x /usr/ucb/ps ] ; then
    EXPLORER_DATA_PS="$( FormatCommandOutput /usr/ucb/ps -wwwwax )"
  else
    EXPLORER_DATA_PS="$( FormatCommandOutput ps -ef )"
  fi

  EXPLORER_DATA_SVCS="$( FormatCommandOutput svcs -avp )"

# OS log files
  LogMsg "Collecting OS logfiles ..."
  EXPLORER_DATA_MESSAGES_FILE="$( ls -l ${SYSTEM_MESSAGE_FILE} )"
  EXPLORER_DATA_SYSLOG_FILE="$( ls -l ${SYSTEM_LOG_FILE} )"

  EXPLORER_DATA_MESSAGES="$( FormatCommandOutput tail -${LOGFILE_LINE_COUNT} "${SYSTEM_MESSAGE_FILE}" )"
  EXPLORER_DATA_SYSLOG="$( FormatCommandOutput tail -${LOGFILE_LINE_COUNT} "${SYSTEM_LOG_FILE}" )"

# xen package information
  LogMsg "Collecting Xen package related information ..."

  XEN_PACKAGE_LIST="$( pkginfo | egrep -i "SUNWvirtinst|SUNWurlgrabber|SUNWlibvirt|SUNWgccruntime|SUNWgnutls|SUNWlibsdl|FSWxwpft|FSWxwrtl|SUNWPython|xen|onbld|xhyp|xvm" | tr -s " " | cut -f2 -d " " )"


# Xen process related information
  LogMsg "Collecting Xen processes related information ..."

  if [ -x /usr/ucb/ps ] ; then
    EXPLORER_DATA_PS_XEN="$( FormatCommandOutput /usr/ucb/ps -wwwwax ' | grep -i xen ' )"
  else
    EXPLORER_DATA_PS_XEN="$( FormatCommandOutput ps -ef ' | grep -i xen ' )"
  fi

  LogMsg "Collecting Xen SMF service related information ..."
  XEN_SERVICES="$( svcs -a -o FMRI | egrep "xen|xctl|xvm" )"

# Xen binaries and config files

  LogMsg "Collecting Xen version information ..."
  PYTHON_VERSION="$( FormatCommandOutput python -V )"
  XM_BINARY="$( FormatCommandOutput whence -v xm )"

#  XEND_CONFIGFILE="$( FormatCommandOutput cat /etc/xen/xend-config.sxp )"
#
  svcprop -q -p config xctl/xend
  if [ $? -eq 0 ] ; then
    XEND_CONFIGFILE="$( FormatCommandOutput svcprop -p config xctl/xend )"
  else
    svcprop -q -p config xvm/xend
    if [ $? -eq 0 ] ; then
      XEND_CONFIGFILE="$( FormatCommandOutput svcprop -p config xvm/xend )"
    else
       XEND_CONFIGFILE="Neither of the services xctl/xend nor xvm/xend found"
     fi
  fi   
  
  XEN_EVENTS="$( FormatCommandOutput syseventadm list )"
  
# Xen Status

  LogMsg "Collecting Xen status related information ..."
  EXPLORER_DATA_XM_DMESG="$( FormatCommandOutput xm dmesg)"
  EXPLORER_DATA_XM_INFO="$( FormatCommandOutput xm info)"
  EXPLORER_DATA_XM_TOP="$( FormatCommandOutput xentop -i 1 -b )"
  EXPLORER_DATA_XM_LIST="$( FormatCommandOutput xm list)" 
  EXPLORER_DATA_XM_LIST_L="$( FormatCommandOutput xm list --long )"

  EXPLORER_DATA_XM_VCPULIST="$( FormatCommandOutput xm vcpu-list )"
  EXPLORER_DATA_XM_LISTLOG="$( FormatCommandOutput xm log "| tail -${LOGFILE_LINE_COUNT}" )"

  EXPLORER_DATA_XM_XENVER="$( FormatCommandOutput echo "xenver::print " \| mdb -k )"
  EXPLORER_DATA_XEN_DEVICES="$( FormatCommandOutput ls -l /dev/xen /devices/xpvd )"
#  EXPLORER_DATA_XEN_DEVICES="$( FormatCommandOutput  ls -l /dev/tty* /devices/*tty* )"


# Xen logfiles
  LogMsg "Collecting Xen logfiles ..."

  XEN_LOGFILES=$( ls /var/log/xen/* 2>/dev/null )

# directories used by Xen

  LogMsg "Collecting Xen filesystem related information ..."

  XEN_DIRS="
/var/lib/xend
/var/lib/xend/domains
/var/lib/xend/storage
/var/lib/xen
/var/lib/xenstored
/var/xen/dump
/var/run/xend
/var/run/xenstored
/usr/lib/xen/bin
/usr/lib/xen/boot
/usr/lib/xen/scripts
/usr/share/xen/qemu/keymaps
         "

# ------------------------------------------------------------------------------------------------------------
# some variable defintions for the html output
#
  SEPARATOR_LINE="<hr style=\"width: 100%; height: 2px;<\">  "
  TITLE="Xen Explorer ${__SCRIPT_VERSION} for ${EXPLORER_DATA_HOST} created at ${EXPLORER_DATA_DATE}"

# ------------------------------------------------------------------------------------------------------------
# create HTML lists

  LogMsg "Creating the first part of the output file ..."

# -----------------------------------------------------------------------------------------------------------
# create the html header

  cat <<EOT >"${OUTPUT_FILE}" 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>${TITLE}</title>
</head>
<body style="background-color: rgb(0, 204, 204);">

<br>
${SEPARATOR_LINE}
<center><strong><a name="top_topic"><a name="top">${TITLE}</center></strong>
<align=left>
${SEPARATOR_LINE}
<br>
<center>
${XEN_STATUS_MSG}
</center>     
<br>
${SEPARATOR_LINE}
EOT


# -----------------------------------------------------------------------------------------------------------
# create the content list

  cat <<EOT >>"${OUTPUT_FILE}" 
<strong>Contents</strong>
<br>
<ul>
<li><a href="#osrelease">General OS Information</a></li>
<li><a href="#networkconfig">Network configuration</a></li>
<li><a href="#processes">Processes and Services</a></li>
<li><a href="#oslogfiles">Solaris logfiles</a></li>

<li><a href="#xen_packages">Xen related installed Packages</a></li>
<li><a href="#xen_processes">Xen related Processes and Services</a></li>
<li><a href="#xenbinaries">Xen Binaries and config files</a></li>
<li><a href="#xenstatus">Xen Status</a></li>
<li><a href="#xenlogfiles">Xen logfiles</a></li>
<li><a href="#xen_dirs">Xen directories</a></li>

<li><a href="#other_configfiles">Other Configfiles</a></li>
<li><a href="#addcmds">Additional commands</a></li>
</ul>
${SEPARATOR_LINE}

EOT

# -----------------------------------------------------------------------------------------------------------
# OS release information
#

# -----------------------------------------------------------------------------------------------------------
# patch information
#

# create the patch list for the html output
#
  PATCH_LIST=""

  for CURPATCH in ${EXPLORER_PATCH_LIST} ; do
    [ "${CURPATCH}"x = "<samp><br></samp>"x ] && continue
    if [[ "${CURPATCH}" ==  *\#\#\#* ]]  ; then
      PATCH_LIST="${PATCH_LIST}  ${CURPATCH}"
   else
      PATCH_LIST="${PATCH_LIST}<li>${CURPATCH}</li>"
    fi
  done   

  cat <<EOT  >>"${OUTPUT_FILE}"
<a name="osrelease" href="#top">General OS Information</a>
<br>
<ul>
<li><a href="#osrelease_general">General</a></li>
<li><a href="#ospatches">Installed Patches</a></li>
<li><a href="#prtdiag">prtdiag</a></li>
<li><a href="#prtconf">prtconf</a></li>
<li><a href="#grubmenu">GRUB Menu</a></li>
<li><a href="#etc_system">/etc/system</a></li>
<li><a href="#module_list">Loaded modules</a></li>
</ul>
<br>
$( PrintSeparator "osrelease_general" "top" "ospatches"  )   
<a name="osrelease_general" href="#osrelease">General information</a>
<br><br>
<table border="1">
<tr>
<th>System info</th>
<td>${EXPLORER_DATA_UNAME_A}</td>
<tr>
<th>Instruction set</th>
<td>${EXPLORER_DATA_ISA_INFO_V}</td>
</tr>
<tr>
<th>Installed Release</th>
<td>${EXPLORER_DATA_RELEASE}</td>
</tr>
<tr>
<th>Installcluster</th>
<td>${EXPLORER_DATA_INSTALL_CLUSTER}</td>
</tr>
</table>

$( PrintSeparator "ospatches" "osrelease_general"  "prtdiag" )   
<a name="ospatches" href="#osrelease_general">Installed Patches</a>
<br>
<ul>
${PATCH_LIST}
</ul>

<br>
$( PrintSeparator "prtdiag" "ospatches" "prtconf" )   
<a name="prtdiag" href="#osrelease">prtdiag</a>
<br><br>
${EXPLORER_DATA_PRTDIAG}

<br>
$( PrintSeparator "prtconf" "prtdiag" "grubmenu" )   
<a name="prtconf" href="#osrelease">prtconf</a>
<br><br>
${EXPLORER_DATA_PRTCONF}

<br>
$( PrintSeparator "grubmenu" "prtconf" "etc_system" )   
<a name="grubmenu" href="#osrelease">GRUB Menu</a>
<br><br>
${EXPLORER_DATA_GRUBMENU}

<br>
$( PrintSeparator "etc_system" "grubmenu" "module_list" )   
<a name="etc_system" href="#osrelease">/etc/system</a>
<br><br>
${EXPLORER_DATA_ETCSYSTEM}

<br>
$( PrintSeparator "module_list" "etc_system" "networkconfig" )   
<a name="module_list" href="#osrelease">Loaded Modules</a>
<br><br>
${EXPLORER_DATA_MODINFO}
<br>
EOT



# -----------------------------------------------------------------------------------------------------------
# network configuration
#


  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "networkconfig" "module_list" "networkconfig_ifconfig" )   

<a name="networkconfig" href="#top">Network configuration</a>
<br>
<ul>
<li><a href="#networkconfig_ifconfig">Network adapter configuration</a></li>
<li><a href="#networkconfig_routes">Routing configuration</a></li>
<li><a href="#networkconfig_nameserver">Nameresolution configuration</a></li>
</ul>

<br>
$( PrintSeparator "networkconfig_ifconfig" "networkconfig" "networkconfig_routes" )   
<a name="networkconfig_ifconfig" href="#networkconfig">Network adapter configuration</a>
<br><br>
${EXPLORER_DATA_NETWORK_CONFIG}
<br>

$( PrintSeparator "networkconfig_routes" "networkconfig_ifconfig" "networkconfig_nameserver" )   
<a name="networkconfig_routes" href="#networkconfig">Routing configuration</a>
<br><br>
${EXPLORER_DATA_ROUTING_CONFIG}
<br>

$( PrintSeparator "networkconfig_nameserver" "networkconfig_routes" "processes" )   
<a name="networkconfig_nameserver" href="#networkconfig">Name resolution configuration</a>
<br><br>
${EXPLORER_DATA_NAMERESOLUTION_CONFIG}
<br>
EOT


# -----------------------------------------------------------------------------------------------------------
# processes and services
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "processes" "networkconfig_nameserver" "process_list" )   
<a name="processes" href="#top">Processes and Services</a>
<br>
<ul>
<li><a href="#process_list">Processes</a></li>
<li><a href="#smf_list">SMF Services</a></li>
</ul>

<br>
$( PrintSeparator "process_list" "processes" "smf_list" )   
<a href="#processes" name="process_list">Processes</a>
<br><br>
${EXPLORER_DATA_PS}

<br>
$( PrintSeparator "smf_list" "process_list" "oslogfiles" )   
<a href="#processes" name="smf_list">SMF Services</a>
<br><br>
${EXPLORER_DATA_SVCS}
<br>
EOT


# -----------------------------------------------------------------------------------------------------------
# OS log files
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "oslogfiles" "smf_list" "var_adm_messages" )   
<a name="oslogfiles" href="#top">Solaris logfiles</a>
<br>
<ul>
<li><a href="#var_adm_messages">${SYSTEM_MESSAGE_FILE}</a></li>
<li><a href="#var_log_syslog">${SYSTEM_LOG_FILE}</a></li>
</ul>

<br>
$( PrintSeparator "var_adm_messages" "oslogfiles" "var_log_syslog" )   
<a name="var_adm_messages" href="#oslogfiles">$( ls -l ${SYSTEM_MESSAGE_FILE} )</a>
<br><br>
${EXPLORER_DATA_MESSAGES}

<br>
$( PrintSeparator "var_log_syslog" "var_adm_messages" "xen_packages" )   
<a name="var_log_syslog" href="#oslogfiles">$( ls -l ${SYSTEM_LOG_FILE})</a>
<br><br>
${EXPLORER_DATA_SYSLOG}
<br>
EOT


# ===========================================================================================================
# xen related infos

# -----------------------------------------------------------------------------------------------------------
# xen package information
#


  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xen_packages" "var_log_syslog" "xen_processes" )   
<a name="xen_packages" href="#top">Xen related installed Packages</a>
<br>
<ul>
EOT

  for CURPKG in ${XEN_PACKAGE_LIST} ; do
    cat <<EOT  >>"${OUTPUT_FILE}"
<li><a href=#${CURPKG}>${CURPKG}</a></li>  
EOT
  done

  cat <<EOT  >>"${OUTPUT_FILE}"
</ul>
<br>
The package information in detail:
<br>
<table border="1">
EOT

  for CURPKG in ${XEN_PACKAGE_LIST} ; do
    cat  <<EOT >>"${OUTPUT_FILE}"
<tr>
<th><a href="#xen_packages" name="${CURPKG}">${CURPKG}</a></th>
<td>$( FormatCommandOutput pkginfo -l ${CURPKG} )</td>
</tr>
EOT
  done

  cat  <<EOT >>"${OUTPUT_FILE}"
</table>
EOT

# -----------------------------------------------------------------------------------------------------------
# xen related processes and services
#
  if [ "${XEN_SERVICES}"x = ""x ] ; then
    EXPLORER_DATA_SVCS_XEN="$( PrintErrorMsg "No Xen related SMF services found" )"
  else 
    EXPLORER_DATA_SVCS_XEN="<ul>"
    for CURSERVICE in ${XEN_SERVICES} ; do
       EXPLORER_DATA_SVCS_XEN="${EXPLORER_DATA_SVCS_XEN}
<li><a href=\"#XEN_SMF_SERVICE_${CURSERVICE}\">${CURSERVICE}</a>
<a href=\"#XEN_SMF_SERVICE_${CURSERVICE}_LOG\">(Logfile)</a></li>"
    done
    EXPLORER_DATA_SVCS_XEN="${EXPLORER_DATA_SVCS_XEN}</ul>"
  fi

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xen_processes" "xen_packages" "process_list_xen" )   
<a name="xen_processes" href="#top">Xen related Processes and Services</a>
<br>
<ul>
<li><a href="#process_list_xen">Xen related Processes</a></li>
<li><a href="#smf_list_xen">Xen related SMF Services</a></li>
</ul>

<br>
$( PrintSeparator "process_list_xen" "xen_processes" "smf_list_xen" )   
<a href="#xen_processes" name="process_list_xen">Xen related Processes</a>
<br><br>
${EXPLORER_DATA_PS_XEN}

<br>
$( PrintSeparator "smf_list_xen" "process_list_xen" "xen_binaries" )   
<a href="#xen_processes" name="smf_list_xen">Xen related SMF Services</a>
<br>
${EXPLORER_DATA_SVCS_XEN}
<br>
${SEPARATOR_LINE}    
EOT

  for CURSERVICE in ${XEN_SERVICES} ; do

     CURFILE=$( svcprop -p "restarter/logfile" "${CURSERVICE}" 2>/dev/null )
     echo "No logfile property defined for the service ${CURSERVICE}" >"${__TEMPFILE1}"
     [ "${CURFILE}"x = ""x ] && CURFILE="${__TEMPFILE1}"

     cat <<EOT >>"${OUTPUT_FILE}"
<a href="#smf_list_xen" name="XEN_SMF_SERVICE_${CURSERVICE}">${CURSERVICE}</a>
<br><br>
$( FormatCommandOutput svcs -xv "${CURSERVICE}" )
<br>
<br>
<a href="#smf_list_xen" name="XEN_SMF_SERVICE_${CURSERVICE}_LOG">Logfile of the service "${CURSERVICE}"</a>
<br>
<br>
$( FormatCommandOutput tail -${LOGFILE_LINE_COUNT} "${CURFILE}" )
<br>
<a href="#smf_list_xen" name="XEN_SMF_SERVICE_${CURSERVICE}_Prop">Properties of the service "${CURSERVICE}"</a>
<br>
<br>
$( FormatCommandOutput svcprop ${CURSERVICE} )
<br>
${SEPARATOR_LINE}
EOT
  done

# -----------------------------------------------------------------------------------------------------------
# Xen binaries and config files

# svcprop -p config xctl/xend


  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xen_binaries" "smf_list_xen" "xend_configfile" )   

<a name="xenbinaries" href="#top">Xen binaries and config files</a>
<br>
<ul>

<li><a href="#xend_configfile">xend configuration</a></li>
<li><a href="#xm_binary">xm Binary</a></li>
<li><a href="#python_binary">Python Version</a></li>
</ul>

<br>
$( PrintSeparator "xend_configfile" "xen_binaries" "xm_binary" )   
<a href="#xenbinaries" name="xend_configfile">xend configuration</a>
<br>
<br>
${XEND_CONFIGFILE}

<br>
$( PrintSeparator "xm_binary" "xend_configfile" "python_binary" )   
<a href="#xenbinaries" name="xm_binary">xm binary</a>
<br>
<br>
${XM_BINARY}

<br>
$( PrintSeparator "python_binary" "xm_binary" "xen_status" )   
<a href="#xenbinaries" name="python_binary">Python Version</a>
<br>
<br>
${PYTHON_VERSION}
<br>
EOT


# -----------------------------------------------------------------------------------------------------------
# XM status
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xen_status" "python_binary" "xm_dmesg" )   
<a name="xenstatus" href="#top">Xen Status</a>
<br>
<ul>
<li><a href="#xm_dmesg">xm dmesg</a></li>
<li><a href="#xm_info">xm info</a></li>
<li><a href="#xm_top">xm top</a></li>
<li><a href="#xm_list">xm list</a></li>
<li><a href="#xm_list_l">xm list --long</a></li>

<li><a href="#xm_vcpulist">xm vcpu-list</a></li>
<li><a href="#xm_listlog">xm log</a></li>

<li><a href="#xm_xenver">xenver</a></li>
<li><a href="#xm_xen_devices">xen devices</a></li>
<li><a href="#xen_events">xen event handler</a></li>
</ul>

<br>
$( PrintSeparator "xm_dmesg" "xen_status"  "xm_info" )   
<a href="#xenstatus" name="xm_dmesg">xm dmesg</a>
<br>
<br>
${EXPLORER_DATA_XM_DMESG}

<br>
$( PrintSeparator "xm_info" "xm_dmesg" "xm_list" )
<a href="#xenstatus" name="xm_info">xm info</a>
<br>
<br>
${EXPLORER_DATA_XM_INFO}

<br>
$( PrintSeparator "xm_list" "xm_info" "xm_top" )
<a href="#xenstatus" name="xm_list">xm list</a>
<br>
<br>
${EXPLORER_DATA_XM_LIST}


<br>
$( PrintSeparator "xm_top" "xm_list" "xm_list_l" )
<a href="#xenstatus" name="xm_top">xm top</a>
<br>
<br>
${EXPLORER_DATA_XM_TOP}

<br>
$( PrintSeparator "xm_list_l" "xm_top" "xm_vcpulist" )
<a href="#xenstatus" name="xm_list_l">xm list --long</a>
<br>
<br>
${EXPLORER_DATA_XM_LIST_L}

<br>
$( PrintSeparator "xm_vcpulist" "xm_list_l" "xm_listlog" )
<a href="#xenstatus" name="xm_vcpulist">xm vcpu-list</a>
<br>
<br>
${EXPLORER_DATA_XM_VCPULIST}

<br>
$( PrintSeparator "xm_listlog" "xm_vcpulist" "xm_xenver" )
<a href="#xenstatus" name="xm_listlog">xm log</a>
<br>
<br>
${EXPLORER_DATA_XM_LISTLOG}

<br>
$( PrintSeparator "xm_xenver" "xm_listlog" "xm_xen_devices" )
<a href="#xenstatus" name="xm_xenver">xenver</a>
<br>
<br>
${EXPLORER_DATA_XM_XENVER}

<br>
$( PrintSeparator "xm_xen_devices" "xm_xenver" "xen_events" )
<a href="#xenstatus" name="xm_xen_devices">xen devices</a>
<br>
<br>
${EXPLORER_DATA_XEN_DEVICES}

<br>

$( PrintSeparator "xen_events" "xm_xen_devices" "xenlogfiles"  )
<a href="#xenstatus" name="xen_events">xen event handler</a>
<br>
${XEN_EVENTS}

<br>

EOT


# -----------------------------------------------------------------------------------------------------------
# Xen Logfiles
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xenlogfiles" "xen_events" "xen_dirs" )
<a name="xenlogfiles" href="#top">Xen logfiles</a>
EOT

  if [ "${XEN_LOGFILES}"x = ""x ] ; then
    cat <<EOT  >>"${OUTPUT_FILE}"
<br>
<br>
$( PrintErrorMsg "No Xen logfiles found in /var/log/xen" )
<br><br>
EOT
  else
    echo "<ul>" >>"${OUTPUT_FILE}"
    for CURFILE in ${XEN_LOGFILES} ; do
       [ ! -f "${CURFILE}" ] && continue
       TAGNAME="${CURFILE##*/}"  
       echo "<li><a href=\"#${TAGNAME}\">${CURFILE}</a></li> ">>"${OUTPUT_FILE}"
    done
    echo "</ul><br>" >>"${OUTPUT_FILE}"

    for CURFILE in ${XEN_LOGFILES} ; do
       [ ! -f "${CURFILE}" ] && continue
       TAGNAME="${CURFILE##*/}"  
    
      cat <<EOT  >>"${OUTPUT_FILE}"
${SEPARATOR_LINE}    
<a href="#xenlogfiles" name="${TAGNAME}">$( ls -l ${CURFILE} )</a>
<br><br>
$( FormatCommandOutput tail -${LOGFILE_LINE_COUNT} "${CURFILE}" )
<br>
EOT
    done 
  fi

# ===========================================================================================================
# directories used by xen
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "xen_dirs"  "xenlogfiles"  "other_configfiles"  )
<a name="xen_dirs" href="#top">Directories used by Xen</a>
EOT

  echo "<ul>" >>"${OUTPUT_FILE}"
  for CURDIR in ${XEN_DIRS} ; do
     echo "<li><a href=\"#${CURDIR}\">${CURDIR}</a></li> ">>"${OUTPUT_FILE}"
  done
  echo "</ul><br>${SEPARATOR_LINE}" >>"${OUTPUT_FILE}"

  for CURDIR in ${XEN_DIRS} ; do
    if [ -d "${CURDIR}" ] ; then
      cat <<EOT  >>"${OUTPUT_FILE}"
${SEPARATOR_LINE}    
<a href="#xen_dirs" name="${CURDIR}">$( ls -ld ${CURDIR} )</a>
<br>
<br>
$( FormatCommandOutput ls -lR  "${CURDIR}" )
<br>
${SEPARATOR_LINE}
EOT
    else
      cat <<EOT  >>"${OUTPUT_FILE}"
${SEPARATOR_LINE}    
<a href="#xen_dirs" name="${CURDIR}">The directory ${CURDIR} does NOT exist</a>
<br>
${SEPARATOR_LINE}
EOT
    fi
  done 


# -----------------------------------------------------------------------------------------------------------
# other files
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "other_configfiles" "xenlogfiles" "addcmds" )
<a name="other_configfiles" href="#top">Other config files</a>
EOT

  if [ ${XEN_CONFIG_FILE_ARRAY[0]} = 0 ] ; then
    cat <<EOT  >>"${OUTPUT_FILE}"
<br><br>
No other config files defined for this run
<br>
EOT
  else
    LogMsg "Collecting additional config files ..."

    echo "<br><ul>">>"${OUTPUT_FILE}"

    i=0
    while [ $i -lt ${XEN_CONFIG_FILE_ARRAY[0]} ] ; do
      (( i = i +1 ))
      CURCONFIGFILE="${XEN_CONFIG_FILE_ARRAY[$i]}"
      echo "<li><a href=\"#otherconfigfiles${i}\">${CURCONFIGFILE}</a></li>" >>"${OUTPUT_FILE}"
    done

    cat <<EOT >>"${OUTPUT_FILE}" 
</ul><br>
${SEPARATOR_LINE}
EOT

    i=0
    while [ $i -lt ${XEN_CONFIG_FILE_ARRAY[0]} ] ; do
      (( i = i +1 ))
      CURCONFIGFILE="${XEN_CONFIG_FILE_ARRAY[$i]}"

      cat <<EOT >>"${OUTPUT_FILE}"
<a name="otherconfigfiles${i}" href="#other_configfiles" >$( ls -l  "${CURCONFIGFILE}" )</a>
<br><br>
$( FormatCommandOutput cat "${CURCONFIGFILE}" )
<br>
${SEPARATOR_LINE}
EOT
    done
  fi

# ===========================================================================================================
# additional commands
#

  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "addcmds" "other_configfiles" )
<a name="addcmds" href="#top">Additional commands</a>
EOT

  if [ ${COMMAND_ARRAY[0]} = 0 ] ; then
    cat <<EOT  >>"${OUTPUT_FILE}"
<br><br>
No additional commands defined for this run
<br>
EOT
  else
    LogMsg "Executing additional commands ..."

    echo "<br><ul>">>"${OUTPUT_FILE}"
   
    i=0
    while [ $i -lt ${COMMAND_ARRAY[0]} ] ; do
      (( i = i +1 ))
      CURCMD="${COMMAND_ARRAY[$i]}"
      echo "<li><a href=\"#addcmd${i}\">${CURCMD}</a></li>" >>"${OUTPUT_FILE}"
    done

    cat <<EOT >>"${OUTPUT_FILE}" 
</ul><br>
${SEPARATOR_LINE}
EOT

    i=0
    while [ $i -lt ${COMMAND_ARRAY[0]} ] ; do
      (( i = i +1 ))
      CURCMD="${COMMAND_ARRAY[$i]}"

      cat <<EOT >>"${OUTPUT_FILE}"
<a name="addcmd${i}" href="#addcmds" >Additional command "${CURCMD}"</a>
<br>
EOT

      echo "Should I execute \"${CURCMD}\" (y/N)?\c"
      AskUser ""
      if [ $? -ne ${__TRUE} ] ; then
        LogMsg "Skipped this command"
        cat <<EOT >>"${OUTPUT_FILE}"
<br>
Skipped the command due to user request
<br>
<br>
${SEPARATOR_LINE}
EOT
        continue
      fi

      LogMsg "-" "
Executing the command \"${CURCMD}\" ..."
      CURCMD_OUTPUT="$( FormatCommandOutput ${CURCMD} )"

      cat <<EOT >>"${OUTPUT_FILE}"
<br>
<strong>Output:</strong>
<br>
<br>
${CURCMD_OUTPUT}
<br>
${SEPARATOR_LINE}
EOT
    done
  fi


# create the html footer
#
  cat <<EOT  >>"${OUTPUT_FILE}"
$( PrintSeparator "endoffile" "addcmds" )
<br>
<center>
Output created by <a href="http://home.arcor.de/bnsmb/public/solaris/xen/xen_explorer.sh">xen_explorer.sh</a> (c) <a href="mailto:Bernd.Schemmer@gmx.de">Bernd Schemmer</a> 2007</a>
<br>
</center>
</body>
</html>
EOT
  die ${__MAINRC}

exit
