#!/bin/sh
#
# GoPrint-Service	This is the init script for starting up a GoPrint service.
#
# The following two lines are used by the chkconfig command. Change as is
# appropriate for your application.  They should remain commented.
# chkconfig: 2345 70 30
#
# description: Starts and stops a GoPrint service.  The service is based on the
# name of the /etc/init.d/ symlink being one of 'goprint-agent', 'goprint-gtx',
# or 'goprint-gtx+agent'.
#
# Copyright (c) 2007 GoPrint Systems Inc.
# Portions copyright (c) 1999, 2006 Tanuki Software Inc.
#
# Java Service Wrapper sh script.  Suitable for starting and stopping
# wrapped Java applications on UNIX platforms.
#
# IMPORTANT NOTES:
# The RUN_AS_USER variable has been fixed as of July 2011 but it still must be
# embedded in this script, which will get overwritten on updates.
#
# If the Java Service Wrapper cannot write to its main log file (wrapper.log)
# it will not start up!

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

# Agent service configuration values
agentCommandName="goprint-agent"		# symlink name for /etc/init.d, and
agentConf="agent.conf"					# .conf file to use from gs4/bin

# GTX service configuration values
gtxCommandName="goprint-gtx"
gtxConf="gtx.conf"

# GTX + Agent configuration values
gtxAgentCommandName="goprint-gtx+agent"
gtxAgentConf="gtx-agent.conf"

# Find the command name that started this script
commandName=`basename $0`
# Lower-case to be case insensitive
commandName=`echo $commandName | tr [:upper:] [:lower:]`
# Find any prefix which would be present with the SysV style run levels
runPrefix=`expr $commandName : '[SsKk][[:digit:]]*'`
if [ "$runPrefix" -ne "0" ]; then
	commandLength=`expr $commandName : '.*'`
	runPrefix=`expr $runPrefix + 1`
	commandName=`expr substr $commandName $runPrefix $commandLength`
fi 
# Determine how to execute based on the command name
if [ $commandName = $agentCommandName ]
then
	APP_NAME="GS4Agent"
	APP_LONG_NAME="GoPrint Agent Service"
	WRAPPER_CONF=$agentConf
elif [ $commandName = $gtxCommandName ]
then
	APP_NAME="GS4GTX"
	APP_LONG_NAME="GoPrint GTX Service"
	WRAPPER_CONF=$gtxConf
elif [ $commandName = $gtxAgentCommandName ]
then
	APP_NAME="GS4GTXAgent"
	APP_LONG_NAME="GoPrint GTX and Agent Service"
	WRAPPER_CONF=$gtxAgentConf
else
	echo "Unrecognized service name."
	exit
fi

# Wrapper - You must create a symlink named 'wrapper' in the gs4/bin directory
# that references the correct binary to use for your platform.  If the symlink
# does not exist then there is logic below from the original Tanuki code that
# tries to guess the best wrapper-* binary to use based on uname output.
WRAPPER_CMD="./wrapper"

# Priority at which to run the wrapper.  See "man nice" for valid priorities.
#  nice is only used if a priority is specified.
PRIORITY=

# Location of the pid file.
PIDDIR="/var/run"

# If uncommented, causes the Wrapper to be shutdown using an anchor file.
#  When launched with the 'start' command, it will also ignore all INT and
#  TERM signals.
#IGNORE_SIGNALS=true

# If specified, the Wrapper will be run as the specified user.
# IMPORTANT - Make sure that the user has the required privileges to write
#  the PID file and wrapper.log files.  Failure to be able to write the log
#  file will cause the Wrapper to exit without any way to write out an error
#  message.
# NOTE - This will set the user which is used to run the Wrapper as well as
#  the JVM and is not useful in situations where a privileged resource or
#  port needs to be allocated prior to the user being changed.
#RUN_AS_USER=

# Do not modify anything beyond this point
#-----------------------------------------------------------------------------

# Get the absolute path to the script
case $0 in
    /*)
        SCRIPT="$0"
        ;;
    *)
        PWD=`pwd`
        SCRIPT="$PWD/$0"
        ;;
esac

# Resolve any sym links to find the real path.  This is done to find the
# Java Service Wrapper binary as this script must reside in the same directory
# as those binaries.
CHANGED=true
while [ "X$CHANGED" != "X" ]
do
    # Change spaces to ":" so the tokens can be parsed.
    SAFESCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
    # Get the real path to this script, resolving any symbolic links
    TOKENS=`echo $SAFESCRIPT | sed -e 's;/; ;g'`
    REALPATH=
    for C in $TOKENS; do
        # Change any ":" in the token back to a space.
        C=`echo $C | sed -e 's;:; ;g'`
        REALPATH="$REALPATH/$C"
        # If REALPATH is a sym link, resolve it.  Loop for nested links.
        while [ -h "$REALPATH" ] ; do
            LS="`ls -ld "$REALPATH"`"
            LINK="`expr "$LS" : '.*-> \(.*\)$'`"
            if expr "$LINK" : '/.*' > /dev/null; then
                # LINK is absolute.
                REALPATH="$LINK"
            else
                # LINK is relative.
                REALPATH="`dirname "$REALPATH"`""/$LINK"
            fi
        done
    done

    if [ "$REALPATH" = "$SCRIPT" ]
    then
        CHANGED=""
    else
        SCRIPT="$REALPATH"
    fi
done
WRAPPER_BIN_DIR="`dirname $REALPATH`"

if [ ! -e "$WRAPPER_BIN_DIR/../jre" ]; then
  echo "Please make a 'jre' symlink in the installation directory that"
  echo "references an Oracle Java installation."
  exit 1
fi

# If the PIDDIR is relative, set its value relative to the wrapper binary location to avoid
# problems if the working directory is later changed.
FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
    PIDDIR=$WRAPPER_BIN_DIR/$PIDDIR
fi
# Same test for WRAPPER_CMD
FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
    WRAPPER_CMD=$WRAPPER_BIN_DIR/$WRAPPER_CMD
fi
# Same test for WRAPPER_CONF
FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
    WRAPPER_CONF=$WRAPPER_BIN_DIR/$WRAPPER_CONF
fi

# Process ID
ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
PIDFILE="$PIDDIR/$APP_NAME.pid"
LOCKDIR="/var/lock/subsys"
LOCKFILE="$LOCKDIR/$APP_NAME"
pid=""

# Resolve the location of the 'ps' command
PSEXE="/usr/bin/ps"
if [ ! -x "$PSEXE" ]
then
    PSEXE="/bin/ps"
    if [ ! -x "$PSEXE" ]
    then
        echo "Unable to locate 'ps'."
        echo "Please report this message along with the location of the command on your system."
        exit 1
    fi
fi

# Resolve the os
DIST_OS=`uname -s | tr [:upper:] [:lower:] | tr -d [:blank:]`
case "$DIST_OS" in
    'sunos')
        DIST_OS="solaris"
        ;;
    'hp-ux' | 'hp-ux64')
        DIST_OS="hpux"
        ;;
    'darwin')
        DIST_OS="macosx"
        ;;
    'unix_sv')
        DIST_OS="unixware"
        ;;
esac

# Resolve the architecture
DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
if [ "$DIST_ARCH" = "unknown" ]
then
    DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
fi
case "$DIST_ARCH" in
    'amd64' | 'athlon' | 'ia32' | 'ia64' | 'i386' | 'i486' | 'i586' | 'i686' | 'x86_64')
        DIST_ARCH="x86"
        ;;
    'ip27')
        DIST_ARCH="mips"
        ;;
    'power' | 'powerpc' | 'power_pc' | 'ppc64')
        DIST_ARCH="ppc"
        ;;
    'pa_risc' | 'pa-risc')
        DIST_ARCH="parisc"
        ;;
    'sun4u' | 'sparcv9')
        DIST_ARCH="sparc"
        ;;
    '9000/800')
        DIST_ARCH="parisc"
        ;;
esac

outputFile() {
    if [ -f "$1" ]
    then
        echo "  $1 (Found but not executable.)";
    else
        echo "  $1"
    fi
}

# Decide on the wrapper binary to use.  If a symbolic link named 'wrapper'
# exists then we will use that as the default.
#  If a 32-bit wrapper binary exists then it will work on 32 or 64 bit
#  platforms, if the 64-bit binary exists then the distribution most
#  likely wants to use long names.
#  For macosx, we also want to look for universal binaries.
if [ ! -x "$WRAPPER_CMD" ]
then
    WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
    if [ -x "$WRAPPER_TEST_CMD" ]
    then
        WRAPPER_CMD="$WRAPPER_TEST_CMD"
    else
        if [ "$DIST_OS" = "macosx" ]
        then
            WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-32"
            if [ -x "$WRAPPER_TEST_CMD" ]
            then
                WRAPPER_CMD="$WRAPPER_TEST_CMD"
            else
                WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
                if [ -x "$WRAPPER_TEST_CMD" ]
                then
                    WRAPPER_CMD="$WRAPPER_TEST_CMD"
                else
                    WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-64"
                    if [ -x "$WRAPPER_TEST_CMD" ]
                    then
                        WRAPPER_CMD="$WRAPPER_TEST_CMD"
                    else
                        if [ ! -x "$WRAPPER_CMD" ]
                        then
                            echo "Unable to locate any of the following binaries:"
                            outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
                            outputFile "$WRAPPER_CMD-$DIST_OS-universal-32"
                            outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
                            outputFile "$WRAPPER_CMD-$DIST_OS-universal-64"
                            outputFile "$WRAPPER_CMD"
                            exit 1
                        fi
                    fi
                fi
            fi
        else
            WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
            if [ -x "$WRAPPER_TEST_CMD" ]
            then
                WRAPPER_CMD="$WRAPPER_TEST_CMD"
            else
                if [ ! -x "$WRAPPER_CMD" ]
                then
                    echo "Unable to locate any of the following binaries:"
                    outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
                    outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
                    outputFile "$WRAPPER_CMD"
                    exit 1
                fi
            fi
        fi
    fi
fi

# Build the nice clause
if [ "X$PRIORITY" = "X" ]
then
    CMDNICE=""
else
    CMDNICE="nice -$PRIORITY"
fi

# Build the anchor file clause.
if [ "X$IGNORE_SIGNALS" = "X" ]
then
   ANCHORPROP=
   IGNOREPROP=
else
   ANCHORPROP=wrapper.anchorfile=\"$ANCHORFILE\"
   IGNOREPROP=wrapper.ignore_signals=TRUE
fi

# Build the lock file clause.  Only create a lock file if the lock directory exists on this platform.
LOCKPROP=
if [ -d $LOCKDIR ]
then
    if [ -w $LOCKDIR ]
    then
        LOCKPROP=wrapper.lockfile=\"$LOCKFILE\"
    fi
fi

# Resolve the location of the 'id' command
IDEXE="/usr/bin/id"
if [ ! -x "$IDEXE" ]
then
    echo "Unable to locate 'id'."
    echo "Please report this message along with the location of the command on your system."
    exit 1
fi

# Resolve the run-as user's primary group 
RUN_AS_GROUP=""
if [ "X$RUN_AS_USER" != "X" ]
then
    RUN_AS_GROUP=`$IDEXE -Gn $RUN_AS_USER | awk '{print $3}' | tail -1`
    if [ "X$RUN_AS_GROUP" = "X" ]
    then
        RUN_AS_GROUP=$RUN_AS_USER
    fi
fi

# RUN_AS_PREFIX is set by checkUser() prior to a start, console, or restart operation.
# Command lines that start the app must be prefixed with whatever is stored in this variable
# after checkUser() has been invoked.
RUN_AS_PREFIX=""

checkUser() {
    # Check the configured run-as user.
    if [ "X$RUN_AS_USER" != "X" ]
    then
        if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
        then
            # Already running as the configured user.  Avoid password prompts by not calling su.
            RUN_AS_USER=""
        fi
    fi
    if [ "X$RUN_AS_USER" != "X" ]
    then
        # If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
        # able to create the lock file.  The Wrapper will be able to update this file once it
        # is created but will not be able to delete it on shutdown.
        if [ "X$LOCKPROP" != "X" ]
        then
            touch $LOCKFILE
            chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
        fi

        # Set the prefix to use with commands to run them as the specified user.
	RUN_AS_PREFIX="su -m $RUN_AS_USER -c"
    fi
}

cleanupLockfile() {
    # Clean up the lock file.
    if [ "X$LOCKPROP" != "X" ]
    then
        getpid
	if [ "X$pid" = "X" ]
	then
	    # Wrapper is not running so make sure the lock file is deleted.
	    if [ -f "$LOCKFILE" ]
	    then
	        rm "$LOCKFILE"
	    fi
	fi
    fi
}

getpid() {
    if [ -f "$PIDFILE" ]
    then
        if [ -r "$PIDFILE" ]
        then
            pid=`cat "$PIDFILE"`
            if [ "X$pid" != "X" ]
            then
                # It is possible that 'a' process with the pid exists but that it is not the
                #  correct process.  This can happen in a number of cases, but the most
                #  common is during system startup after an unclean shutdown.
                # The ps statement below looks for the specific wrapper command running as
                #  the pid.  If it is not found then the pid file is considered to be stale.
		# Note that we grep for 'wrapper' only as sometimes ps will chop the
		# program name in the process list, yet all names have 'wrapper' in them
		# and it's unlikely to chop that early.
                pidtest=`$PSEXE -p $pid | grep "wrapper" | tail -1`
                if [ "X$pidtest" = "X" ]
                then
                    # This is a stale pid file.
                    rm -f "$PIDFILE"
                    echo "Removed stale pid file: $PIDFILE"
                    pid=""
                fi
                # Consider: Execute 'ps' again with -p $pid -o args to verify .conf file is the same?
            fi
        else
            echo "Cannot read $PIDFILE."
            exit 1
        fi
    fi
}

reservepid() {
    if [ "X$RUN_AS_USER" != "X" ]
    then
        # If RUN_AS_USER is defined that user will most likely not be able to create the PIDFILE.
	touch $PIDFILE
        chown $RUN_AS_USER:$RUN_AS_GROUP $PIDFILE
    fi
}

testpid() {
    pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
    if [ "X$pid" = "X" ]
    then
        # Process is gone so remove the pid file.
        rm -f "$PIDFILE"
        pid=""
    fi
}

console() {
    echo "Running $APP_LONG_NAME..."
    getpid
    if [ "X$pid" = "X" ]
    then
        reservepid
        # The string passed to eval must handles spaces in paths correctly.  Quotes are not added
	# around WRAPPER_CMD or WRAPPER_CONF at this point - they must be added prior to this if needed.
        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" $ANCHORPROP $LOCKPROP"
	if [ "X$RUN_AS_PREFIX" != "X" ]
	then
	    SAFECMDLINE=`echo $COMMAND_LINE | sed -e 's;\";\\\";g'`
	    COMMAND_LINE="$RUN_AS_PREFIX -- \"$SAFECMDLINE\""
	fi
        eval $COMMAND_LINE
    else
        echo "$APP_LONG_NAME is already running."
        exit 1
    fi
}
 
startService() {
    echo "Starting $APP_LONG_NAME..."
    getpid
    if [ "X$pid" = "X" ]
    then
        reservepid
        # The string passed to eval must handle spaces in paths correctly.  Quotes are not added
	# around WRAPPER_CMD or WRAPPER_CONF at this point - they must be added prior to this if needed.
        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $LOCKPROP"
	if [ "X$RUN_AS_PREFIX" != "X" ]
	then
	    SAFECMDLINE=`echo $COMMAND_LINE | sed -e 's;\";\\\";g'`
	    COMMAND_LINE="$RUN_AS_PREFIX -- \"$SAFECMDLINE\""
	fi
        eval $COMMAND_LINE
    else
        echo "$APP_LONG_NAME is already running."
        exit 1
    fi
}
 
stopService() {
    echo "Stopping $APP_LONG_NAME..."
    getpid
    if [ "X$pid" = "X" ]
    then
        echo "$APP_LONG_NAME was not running."
    else
        if [ "X$IGNORE_SIGNALS" = "X" ]
        then
            # Running so try to stop it.
            kill $pid
            if [ $? -ne 0 ]
            then
                # An explanation for the failure should have been given
                echo "Unable to stop $APP_LONG_NAME."
                exit 1
            fi
        else
            rm -f "$ANCHORFILE"
            if [ -f "$ANCHORFILE" ]
            then
                # An explanation for the failure should have been given
                echo "Unable to stop $APP_LONG_NAME."
                exit 1
            fi
        fi

        # We can not predict how long it will take for the wrapper to
        #  actually stop as it depends on settings in wrapper.conf.
        #  Loop until it does.
        savepid=$pid
        CNT=0
        TOTCNT=0
        while [ "X$pid" != "X" ]
        do
            # Show a waiting message every 5 seconds.
            if [ "$CNT" -lt "5" ]
            then
                CNT=`expr $CNT + 1`
            else
                echo "Waiting for $APP_LONG_NAME to exit..."
                CNT=0
            fi
            TOTCNT=`expr $TOTCNT + 1`

            sleep 1

            testpid
        done

        pid=$savepid
        testpid
        if [ "X$pid" != "X" ]
        then
            echo "Failed to stop $APP_LONG_NAME."
            exit 1
        else
	    cleanupLockfile
            echo "Stopped $APP_LONG_NAME."
        fi
    fi
}

status() {
    getpid
    if [ "X$pid" = "X" ]
    then
        echo "$APP_LONG_NAME is not running."
        exit 1
    else
        echo "$APP_LONG_NAME is running ($pid)."
        exit 0
    fi
}

dump() {
    echo "Dumping $APP_LONG_NAME..."
    getpid
    if [ "X$pid" = "X" ]
    then
        echo "$APP_LONG_NAME was not running."

    else
        kill -3 $pid

        if [ $? -ne 0 ]
        then
            echo "Failed to dump $APP_LONG_NAME."
            exit 1
        else
            echo "Dumped $APP_LONG_NAME."
        fi
    fi
}

case "$1" in

    'console')
        checkUser
        console
        ;;

    'start')
        checkUser
        startService
        ;;

    'stop')
        stopService
        ;;

    'restart')
        checkUser
        stopService
        startService
        ;;

    'zap')
        cleanupLockfile
	;;

    'status')
        status
        ;;

    'dump')
        dump
        ;;

    *)
        echo "Usage: $0 { console | start | stop | restart | status | dump }"
        exit 1
        ;;
esac

exit 0
