#!/bin/bash
#
# chkconfig: 2345 85 15
# description: Plesk Interface and Utilities	
# processname: sw-cp-server
# config: /etc/sw-cp-server/config
# config: /etc/sw-cp-server/conf.d/plesk.conf
# pidfile: /var/lib/sw-cp-server.pid
# 
# Startup script for the Plesk
#
# Following comments are required for SuSE Linux
#
### BEGIN INIT INFO
# Provides:       plesk psa
# Required-Start: $remote_fs $time mysql
# Required-Stop:
# X-UnitedLinux-Should-Start:
# X-UnitedLinux-Should-Stop:
# Default-Start:  2 3 4 5
# Default-Stop:   0 1 6
# Description:    Start the Plesk Server Administrator
### END INIT INFO
#
#

p_echo()
{
echo "$*"
}



PRODUCT_NAME="psa"
PRODNAME="psa"
PRODUCT_ROOT_D="/usr/local/psa"
PRODUCT_UTILS_DIR="${PRODUCT_ROOT_D}/admin/sbin"
MYSQL_BIN_D="/usr/bin"

rc_d="/etc/init.d"

# Source function library.
[ -f ${rc_d}/functions ] && . ${rc_d}/functions

# Source networking configuration.
[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network

# Source subsystem configuration.
[ -f /etc/sysconfig/$PRODNAME ] && . /etc/sysconfig/$PRODNAME

# this way is for SuSE Linux
test -s /etc/rc.status && . /etc/rc.status && rc_reset

admin_passwd="`cat /etc/$PRODNAME/.$PRODNAME.shadow`"
lockdir="/var/lock/subsys"
optional_service="postgresql"
optional_service_wo_lock="spamassassin"

tomcat_service="tomcat6"
httpd_service="httpd"
named_service="named"
mysqld_service="mysqld"
sw_engine_base_name=sw-engine
sw_engine_process_name="${sw_engine_base_name}-fpm"
LOCKDIR_AVAILABLE="Yes"

service="${named_service}"
ng_services="mailer"

#set openssl config
OPENSSL_CONF="${PRODUCT_ROOT_D}/admin/conf/openssl.cnf"
export OPENSSL_CONF
#set  language
LANG=C
export LANG

if [ -x ${rc_d}/xinetd ]; then
	inetd=xinetd
elif [ -x ${rc_d}/inet ]; then
	inetd=inet
elif [ -x ${rc_d}/openbsd-inetd ]; then
	inetd=openbsd-inetd
elif [ -x ${rc_d}/inetd ]; then
	inetd=inetd
else
	echo "Warning: there is no installed Internet services daemon on your system"
fi

# --- MySQL utility functions ---

get_my_cnf_param()
{
	local my_cnf cnf_files

	cnf_files="/etc/my.cnf /etc/mysql/my.cnf /var/db/mysql/my.cnf"

	for my_cnf in ${cnf_files}; do
		if [ -f ${my_cnf} ]; then
			break
		fi
	done

	[ -f ${my_cnf} ] && r=`perl -e '$p="'"$1"'";
	undef $/; $_=<>; s/#.*$//gm;
	/\[mysqld\](.*?)\[/sg;
	$_=substr($1, rindex $1,"$p") and
	/$p\s*=(.*)/m and print $1
	' ${my_cnf}`
	echo $r
}

setenv_mysql()
{
	mysqlsock=`get_my_cnf_param  socket`
	if [ -S "$mysqlsock" ]; then
		MYSQL_UNIX_PORT=$mysqlsock && export MYSQL_UNIX_PORT
	else
		for i in $MYSQL_SOCKETS
		do
			if [ -S "$i" ]; then
				MYSQL_UNIX_PORT=$i
				export MYSQL_UNIX_PORT
				break
			fi
		done
	fi
}

mysql_connect()
{
	setenv_mysql

	local attempts=${1:-1}
	local msg_timeout=5
	local output
	for i in `seq $attempts`; do 
		output=`echo "" | mysql_raw -Dmysql 2>&1`
		if [ "$?" -eq 0 ]; then
			[ "$i" -gt "$msg_timeout" ] && echo "Connected."
			return 0
		fi
		[ "$attempts" -eq 1 ] || sleep 1
		[ "$i" -eq "$msg_timeout" ] && echo -n "Trying to connect to MySQL... "
	done

	echo "Failed to connect to MySQL: $output" >&2
	return 1
}

mysql_raw()
{
	(
		export MYSQL_PWD="$admin_passwd"
		"$MYSQL_BIN_D/mysql" --user=admin -NBr "$@"
		rc=$?
		unset MYSQL_PWD
		return $rc
	)
}

mysql()
{
	local query="$1"
	shift

	[ -n "$admin_passwd" ] || return 2

	if [ -z "$mysql_is_up" ]; then
		mysql_connect 60 && mysql_is_up="yes" || mysql_is_up="no"
	fi
	[ "$mysql_is_up" = "yes" ] || return 3

	mysql_output=`mysql_raw -D$PRODNAME -e "$query" "$@"`
}

get_misc_param()
{
	local param_name="$1"
	local default_value="$2"
	local param_value rc

	mysql "SELECT val FROM misc WHERE param='$param_name'"
	rc="$?"

	[ -n "$mysql_output" ] && param_value="$mysql_output" || param_value="$default_value"
	eval misc_param__${param_name}="$param_value"
	return $rc
}


get_local_mail_setting()
{
        local setting_name="$1"
        local default_value="$2"
        local setting_val rc

        mysql "SELECT value FROM ServiceNodeConfiguration WHERE serviceNodeId=1 AND section='mailServer' AND name='$setting_name'"
        rc="$?"

        [ -n "$mysql_output" ] && setting_val="$mysql_output" || setting_val="$default_value"
        eval mail_${setting_name}="$setting_val"
        return $rc
}

# --- END of MySQL utility functions ---

clean_sessions()
{
	mysql "DELETE FROM sessions"
	rm -f ${PRODUCT_ROOT_D}/admin/sessions/*
}

define_virusfilter()
{
	local mail_virusfilter
	get_local_mail_setting virusfilter none

	case $mail_virusfilter in
	kav)
		virusfilter_service="kavehost"
		;;
	drweb)
		virusfilter_service="drwebd"
		;;
	*)
		virusfilter_service=""
		;;
	esac
}

rc_syntax()
{
    if test -z "$LINES" -o -z "$COLUMNS" ; then
	eval `exec 3<&1; stty size <&3 2>/dev/null | (read L C; 	echo LINES=${L:-24} COLUMNS=${C:-80})`
    fi

    if test -t 1 -a "$TERM" != "raw" -a "$TERM" != "dumb" && stty size <&1 > /dev/null 2>&1 ; then
	esc=`echo -en "\033"`
	extd="${esc}[1m"
	warn="${esc}[1;31m"
	attn="${esc}[1;33m"
	norm=`echo -en "${esc}[m\017"`
	stat=`echo -en "\015${esc}[${COLUMNS}C${esc}[10D"`
	done="${esc}[1;32m"
    else
	esc=""
	extd=""
	warn=""
	attn=""
	norm=""
	stat=""
	done=""
    fi

    rc_done="${stat}${done}done${norm}"
    rc_started="${stat}${done}already started${norm}"
    rc_stopped="${stat}${done}already stopped${norm}"
    rc_not_installed="${stat}${extd}not installed${norm}"
    rc_failed="${stat}${warn}failed${norm}"
}

get_pids_byname()
{
        proc_name="$1"
        PIDS=`ps axww | awk '$5 ~ "'$proc_name'$" {print $1}'`
        echo $PIDS
}

wait_after_stop()
{
       PIDS=`echo "$1" | tr ' ' ,`
       count=${2:=50}

       for i in `seq $count`; do
               ps -p $PIDS > /dev/null 2>&1 || break
               [ 0$i -eq 0$count ] && kill -9 $1 > /dev/null 2>&1

               sleep 1
       done

       return 0
}


sw_engine_ctl()
{
	local command=$1
	if [ -z "${command}" ]; then
		echo 'Error: command for sw-engine control script is not specified'
		exit 1
	fi
	
	/etc/init.d/${sw_engine_base_name} "${command}"
}


service_start()
{
	local serv_list="$1"

	for i in $serv_list; do
		echo -n "Starting $i service... "
		if [ -f ${rc_d}/$i ]; then
			if [ ! -f ${lockdir}/$i ]; then
				${rc_d}/$i start > /dev/null 2>&1
				res=$?
			fi
			[ 0$res -eq 0 ] && echo "$rc_done" || echo "$rc_failed"
		else
			echo "$rc_not_installed"
		fi
	done
}

service_stop()
{
	local serv_list="$1"
	local lock_flag="$2"

	for i in $serv_list; do
		echo -n "Stopping $i service... "
		if [ -f ${rc_d}/$i ]; then
			if [ -f ${lockdir}/$i -o "X$lock_flag" = "XNo" ]; then
				${rc_d}/$i stop > /dev/null 2>&1
				res=$?
			fi
			[ 0$res -eq 0 ] && echo "$rc_done" || echo "$rc_failed"
		else
			echo "$rc_not_installed"
		fi
	done
}

start_service()
{
	local mode="$1"
	local apache_started=0
	
	# some services need to be stoped before start:
	service_stop "" "No"

	detect_ipv6_support
	start1
	service_start "$inetd sw-cp-server $mysqld_service" 
	if [ "$mode" = "start" ]; then
		check_ip_remap
		check_cloning
	fi
	service_start "$service $optional_service $optional_service_wo_lock"
	psa_common start

	mysql "SELECT COUNT(*) FROM DomainServices WHERE type='tomcat' AND status=0"
	local active_ds="$mysql_output"
	if [ 0$active_ds -gt 0 ]; then
		for i in $tomcat_service; do
			if [ -f ${rc_d}/$i -a ! -f ${lockdir}/$i ]; then
				${PRODUCT_ROOT_D}/admin/sbin/tomcatmng --restart
				apache_started=1
			fi
		done
	fi

	apache_current_status=`${PRODUCT_ROOT_D}/admin/sbin/apache_control_adapter -s`
	if [ "X${apache_current_status}" = "Xis running" ]; then
		apache_started=1
	fi

	for i in $httpd_service; do
        	if [ $apache_started -eq 0 -a -f ${rc_d}/$i ]; then
			${PRODUCT_ROOT_D}/admin/sbin/apache_control_adapter --start
		fi
	done
}

stop_service()
{
	stop

	define_virusfilter
	psa_common stop
	service_stop "$service sw-cp-server $mysqld_service $optional_service" "$LOCKDIR_AVAILABLE"
	service_stop "$optional_service_wo_lock $virusfilter_service" "No"
	service_stop "$tomcat_service" "$LOCKDIR_AVAILABLE"
	service_stop "$httpd_service" "$LOCKDIR_AVAILABLE"

	$PRODUCT_ROOT_D/bin/apache_cleanup.sh
}

start1()
{
	echo -n "Starting ${PRODUCT_NAME}... "

 	if sw_engine_ctl start; then
	    [ -d ${lockdir} ] && touch "$lockdir/$PRODNAME"
	    ${PRODUCT_ROOT_D}/admin/bin/packagemng --set-dirty-flag
	    echo "$rc_done"
	else
	    echo "$rc_failed"
	    return 1
	fi

	return 0
}

make_lockdir()
{
	local plesk_lock_dir="/var/lock/files"
	[ -d "$plesk_lock_dir" ] || mkdir -p $plesk_lock_dir
}

start()
{	
	make_lockdir
	start_service "start"
	sleep 1
	clean_sessions
	start1
	sleep 1
	define_virusfilter
	service_start "$virusfilter_service"
}

stop()
{
	echo -n "Stopping ${PRODUCT_NAME}... "

	sw_engine_ctl stop > /dev/null 2>&1

	if [ -f "$lockdir/$PRODNAME" ]; then
		wait_after_stop "`get_pids_byname "${sw_engine_process_name}"`" 100
		ret=$?

		if [ 0$ret -eq 0 ]; then
		    rm -f "$lockdir/$PRODNAME"
		    echo "$rc_done"
		else
		    echo "$rc_failed"
		    return 1
		fi
	else
		echo "$rc_done"
	fi
	return 0
}

restart()
{

	status $PRODNAME ${sw_engine_process_name} > /dev/null 2>&1

	case $? in

	0)
		sw_engine_ctl restart
		ret=$?
		clean_sessions
		[ $ret -eq 0 ] && ${PRODUCT_ROOT_D}/admin/bin/packagemng --set-dirty-flag
		;;

	*)
		echo "PSA is down, performing full restart. "
		start
		;;
	esac
}

reload()
{
	sw_engine_ctl reload
}

# this routine is psa specific override of standard status function
status()
{
	local base=${1##*/}
	local dbase=${2##*/}
	local pid

	# Test syntax.
	if [ $# = 0 ] ; then
		echo $"Usage: status {service name} {daemon name}"
		return 1
	fi

	# First try "pidof"
	pid=`pidof -o $$ -o $PPID -o %PPID -x $2 || 	     pidof -o $$ -o $PPID -o %PPID -x ${dbase}`
	if [ "$pid" != "" ] ; then
	        echo $"${dbase} (pid $pid) is running..."
	        return 0
	fi

	# Next try "/var/run/*.pid" files
	if [ -f /var/run/${base}.pid ] ; then
	        read pid < /var/run/${base}.pid
	        if [ "$pid" != "" ] ; then
	                echo $"${base} dead but pid file exists"
	                return 1
	        fi
	fi
	# See if /var/lock/subsys/${base} exists
	if [ -f /var/lock/subsys/${base} ]; then
		echo $"${base} dead but subsys locked"
		return 2
	fi
	echo $"${base} is stopped"
	return 3
}

echo_action()
{
	local service="$1"
	local action="$2"

	case $action in
		start) msg="Starting" ;;
		stop) msg="Stopping" ;;
		restart) msg="Restarting" ;;
		*) ;;
	esac

	$service comment

	echo -n "Plesk: $msg $inten... "
	return 0
}

suc()
{
    echo "$rc_done"
	return 0
}

fail()
{
    echo "$rc_failed"
	return 1
}

psa_common()
{
	local action="$1"

	for service in $ng_services; do
		echo_action "$service" "$action"

		$service status
		status="$?"

		# status values:
		# 0 - service is running
		# 1 - service is stopped
		# 2 - service is not installed
		# 3 - service status is undefined and
		#        action must be executed anyway

		if [ "X$status" = "X2" ]; then
		    echo "$rc_not_installed"
			continue;
		fi

		case $action in
			start*)
				if [ "X$status" = "X0" ]; then
					echo "already started"
				else
					$service start && suc || fail
				fi
			;;
			stop*)
				if [ "X$status" = "X1" ]; then
					 echo "already stopped"
				else
					$service stop && suc || fail
				fi
			;;
			restart*)
				if [ "X$status" != "X1" ]; then
					$service stop || fail
				fi
				if [ $? -ne 1 ]; then
					$service start && suc || fail
				fi
			;;
		esac
	done

	return 0
}

mailer()
{
	local action="$1"
	local service
	local driver
	local subservno
	local subservrun

	inten="Mail Server"

	driver="$PRODUCT_UTILS_DIR/mailmng-service"

	if [ ! -x $driver ]; then
		return 2
	fi

	case $action in
		comment) ;;
		start)
			$driver --start-service >/dev/null 2>&1 || return 1
		;;
		stop)
			$driver --stop-service >/dev/null 2>&1 || return 1
		;;
		status)
			# get total number of mailer services
			subservno=`$driver --status-service | wc -l`
			# get number of running services
			subservrun=`$driver --status-service | grep 'is running' | wc -l`
			if [ $subservrun -eq 0 ]; then
				return 1
			fi
			if [ $subservno -ne $subservrun ]; then
				# some mail services are running and some not
				return 3
			fi
		;;
		restart)
			$driver --restart-service  >/dev/null 2>&1 || return 1
		;;
		reload)
			$driver --reload-service  >/dev/null 2>&1 || return 1
		;;
	esac

	return 0
}

check_ip_remap()
{
	local misc_param__ip_auto_remap misc_param__vps_cloning_mode
	get_misc_param ip_auto_remap false
	get_misc_param vps_cloning_mode false

	if [ "$misc_param__ip_auto_remap" = "true" ] && [ "$misc_param__vps_cloning_mode" = "true" ] ; then
		misc_param__ip_auto_remap="false"
	fi
	if [ "$misc_param__ip_auto_remap" = "true" ] ; then
		echo "Checking whether IP reconfiguration is needed..."
		${PRODUCT_ROOT_D}/bin/reconfigurator --autoconfigure
	fi
}

check_cloning() 
{
	local misc_param__vps_cloning_mode
	get_misc_param vps_cloning_mode false

	# If MySQL is still not up yet, reset_instance_data will manage to start it
	if [ "$?" -eq 3 -o "$misc_param__vps_cloning_mode" = "true" ] ; then
		${PRODUCT_ROOT_D}/admin/sbin/reset_instance_data "--do-what-I-say" "--psa-init"
		# MySQL password might have changed - reread it
		admin_passwd="`cat /etc/$PRODNAME/.$PRODNAME.shadow`"
	fi
}

detect_ipv6_support()
{
	local psa_conf="/etc/psa/psa.conf"
	local ipv6_config_file="/etc/sw-cp-server/conf.d/ipv6_ports.inc"

	if [ -f "/proc/net/if_inet6" ]; then
		if grep '^IPv6_DISABLED[[:space:]]*false$' "${psa_conf}" >/dev/null 2>&1; then
			cat > "${ipv6_config_file}" << EOF
listen   [::]:8443 ipv6only=on ssl;
listen   [::]:8880 ipv6only=on;
EOF
			return 0
		fi
	fi

	rm -f "${ipv6_config_file}"
}

rc_syntax

# See how we were called.
case "$1" in
  start)
    start
    ;;
  start1)
    start1
    ;;
  startall)
    start_service "startall"
    ;;
  stop)
    stop
    ;;
  stop1)
    stop
    ;;
  stopall)
    stop_service
    ;;
  status)
    status $PRODNAME ${sw_engine_process_name}
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  restart1)
    stop
    start1
    ;;
  *)
    echo $"Usage: $0 {start|stop|startall|stopall|restart|status}"
    exit 1
esac

exit $?