#!/bin/sh
### Copyright 1999-2012. Parallels IP Holdings GmbH. All Rights Reserved.
#

#
# Plesk script
#


### Copyright 1999-2012. Parallels IP Holdings GmbH. All Rights Reserved.
# Migration manager tables will be managed by plesk

### Copyright 1999-2012. Parallels IP Holdings GmbH. All Rights Reserved.

# echo message to product log and console (always visible)
pp_echo()
{
    if [ -n "$product_log" ] ; then
        echo "$@" >> "$product_log" 2>&1
    fi
    echo "$@"
}

# echo message to product log, unless debug
p_echo()
{
    if [ -n "$PLESK_INSTALLER_DEBUG" -o -n "$PLESK_INSTALLER_VERBOSE" -o -z "$product_log" ] ; then
        echo "$@"
    else
        echo "$@" >> "$product_log" 2>&1
    fi
}

detect_vz()
{
	PLESK_VZ=0
	PLESK_VE_HW_NODE=0
	PLESK_VZ_TYPE=

	local issue_file="/etc/issue"
	local vzcheck_file="/proc/self/status"
	[ -f "$vzcheck_file" ] || return 1

	local env_id=`sed -ne 's|^envID\:[[:space:]]*\([[:digit:]]\+\)$|\1|p' "$vzcheck_file"`
	[ -n "$env_id" ] || return 1
	if [ "$env_id" = "0" ]; then
		# Either VZ/OpenVZ HW node or unjailed CloudLinux
		PLESK_VE_HW_NODE=1
		return 1
	fi

	if grep -q "CloudLinux" "$issue_file" >/dev/null 2>&1 ; then
		return 1
	fi

	if [ -f "/proc/vz/veredir" ]; then
		PLESK_VZ_TYPE="vz"
	elif [ -d "/proc/vz" ]; then
		PLESK_VZ_TYPE="openvz"
	fi

	PLESK_VZ=1
	return 0
}
### Copyright 1999-2012. Parallels IP Holdings GmbH. All Rights Reserved.
# vim:ft=sh

initial_conf()
{
	DEMO_VERSION="no"
	PRODNAME="psa"
	PRODUCT_NAME="psa"
	product_full="Plesk"
	product=${PRODNAME}
	PRODUCT_FULL_NAME="Plesk"

	product_etc="/etc/${PRODNAME}"
	prod_conf_t="/etc/psa/psa.conf"
	prodkey="$product_etc/$PRODNAME.key"

	minimal_changes=""

	EXTERNAL_PACKAGES=""
	EXTERNAL_PACKAGES_DIR=""

	BUILDER_UID="10007"

	PERL5LIB=/usr/local/psa/lib/perl5/site_perl/5.8.8:/usr/local/psa/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi
	export PERL5LIB

        support_contact="http://www.parallels.com/support"
	sales_email="sales@parallels.com"

	product_version="11.5.30"
	product_db_version="011005030"
	conceived_os_vendor=CentOS
	conceived_os_version="5"
	osrels="centos5"

	prev_product="plesk"
	prev_clients_group="${prev_product}cln"

        clients_group="${product}cln"
        clients_GID=10001

        services_group="psaserv"
        services_GID=10003

        product_suff="saved_by_${product}".`date "+%m.%d;%H:%M"`
        product_suffo="saved_by_${product}"

	PREV_PRODUCT_ROOT_D="/usr/local/${prev_product}"

	# plesk default password
	if [ "X$DEMO_VERSION" = "Xyes" ]; then
		PRODUCT_DEFAULT_PASSWORD="plesk"
	else
		PRODUCT_DEFAULT_PASSWORD="setup"
	fi
}

read_conf()
{
	[ -n "$prod_conf_t" ] || prod_conf_t=/etc/psa/psa.conf

	if [ -s $prod_conf_t ]; then
		tmp_var=`perl -e 'undef $/; $_=<>; s/#.*$//gm;
				s/^\s*(\S+)\s*/$1=/mg;
				print' $prod_conf_t`
		eval $tmp_var
	else
		if [ "X$do_upgrade" = "X1" ]; then
			[ 0$ignore_miss_conf -ne 1 ] && p_echo "Unable to find product configuration file: $prod_conf_t"
			return 1
		fi
	fi
	return 0
}

 #default values

product_default_conf()
{

PRODUCT_ROOT_D=/usr/local/psa
PRODUCT_RC_D=/etc/init.d
PRODUCT_ETC_D=/usr/local/psa/etc
PLESK_LIBEXEC_DIR=/usr/lib64/plesk-9.0
HTTPD_VHOSTS_D=/var/www/vhosts
HTTPD_CONF_D=/etc/httpd/conf
HTTPD_INCLUDE_D=/etc/httpd/conf.d
HTTPD_BIN=/usr/sbin/httpd
HTTPD_LOG_D=/var/log/httpd
HTTPD_SERVICE=httpd
QMAIL_ROOT_D=/var/qmail
PLESK_MAILNAMES_D=/var/qmail/mailnames
RBLSMTPD=/usr/sbin/rblsmtpd
FTPD_CONF=/etc/proftpd.conf
FTPD_CONF_INC=/etc/proftpd.include
FTPD_BIN_D=/usr/bin
FTPD_VAR_D=/var/run/proftpd
FTPD_SCOREBOARD=/var/run/proftpd/scoreboard
NAMED_RUN_ROOT_D=/var/named/run-root
NAMED_OPTIONS_CONF=
NAMED_ZONES_CONF=
WEB_STAT=/usr/bin/webalizer
MYSQL_VAR_D=/var/lib/mysql
MYSQL_BIN_D=/usr/bin
MYSQL_SOCKET=/var/lib/mysql/mysql.sock
PGSQL_DATA_D=/var/lib/pgsql/data
PGSQL_CONF_D=/var/lib/pgsql/data
PGSQL_BIN_D=/usr/bin
DUMP_D=/var/lib/psa/dumps
DUMP_TMP_D=/tmp
MAILMAN_ROOT_D=/usr/lib/mailman
MAILMAN_VAR_D=/var/lib/mailman
PYTHON_BIN=/usr/bin/python2.6
CATALINA_HOME=/usr/share/tomcat5
DRWEB_ROOT_D=/opt/drweb
DRWEB_ETC_D=/etc/drweb
GPG_BIN=/usr/bin/gpg
TAR_BIN=/bin/tar
AWSTATS_ETC_D=/etc/awstats
AWSTATS_BIN_D=/var/www/cgi-bin/awstats
AWSTATS_TOOLS_D=/usr/share/awstats
AWSTATS_DOC_D=/var/www/html/awstats
OPENSSL_BIN=/usr/bin/openssl
LIB_SSL_PATH=/lib/libssl.so
LIB_CRYPTO_PATH=/lib/libcrypto.so
CLIENT_PHP_BIN=/usr/local/psa/bin/php-cli
SNI_SUPPORT=false
APS_DB_DRIVER_LIBRARY=/usr/lib64/libmysqlserver.so.2
IPv6_DISABLED=false
SA_MAX_MAIL_SIZE=256000

}
### Copyright 1999-2012. Parallels IP Holdings GmbH. All Rights Reserved.

#set_params

set_common_params()
{
	common_var=0

	PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
	LANG=C
	export PATH LANG
	umask 022
	ulimit -n 65535 2>/dev/null

	K_HUP="/bin/kill -HUP"
	K_KILL="/bin/kill -KILL"
	K_TERM="/bin/kill -TERM"
	K_USR2="/bin/kill -USR2"
	K_TEST="/bin/kill -0"

	users_created=""
	groups_created=""

	certificate_file="$PRODUCT_ETC_D/httpsd.pem"
	services="/etc/services"
	mtab="/etc/mtab"
	get_hostname="hostname"
	get_domainname="domainname"

	#VZP used to determine that we're inside SVE
	vza_file="/var/vzagent"

	#default parameters
	tar="tar"
	crontab="/usr/bin/crontab"

	cp_preserve="cp -p"
	SYSTEM_RC_D=/etc/init.d
	PLESK_LIBEXEC_DIR="/usr/lib64/plesk-9.0"
	PLESK_DB_DIR="/var/lib/plesk"
	POSTFIX_LIBEXEC_DIR="/usr/libexec/postfix"
	PRODUCT_BOOTSTRAPPER_DIR="/usr/local/psa/bootstrapper/pp11.5.30-bootstrapper"
	AUTOGENERATED_CONFIGS="#ATTENTION!\n#\n#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY,\n#SO ALL YOUR CHANGES WILL BE LOST THE NEXT TIME THE FILE IS GENERATED.\n"
	AUTOGENERATED_CONFIGS_UPGRADE="#ATTENTION!\n#\n#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY,\n#SO ALL YOUR CHANGES WILL BE LOST AFTER YOU UPGRADE PARALLELS PLESK PANEL.\n"

	set_common_params_linux 

	detect_vz
}

set_common_params_linux()
{
	get_hostname="hostname -f"
	fstab="/etc/fstab"
	cp_preserve="cp --preserve=all --remove-destination"
	machine="linux"
	sendmail="/usr/sbin/sendmail"
	ps="ps axw"
	ps_long="ps axuw"
	false_shell="/bin/false"
	dummy_home="/"
	compress="gzip -9 -c"
	uncompress="gunzip -c"
	uudecode="uudecode -o /dev/stdout"
	ifconfig="/sbin/ifconfig -a"
	inet_str="inet addr"

	if [ -f /etc/slackware-version ]; then
	    linux_distr="slackware"
	    useradd_options=""
	    sndml_ini="/etc/rc.d/init.d/sendmail"
	    mail_local="/usr/libexec/mail.local"
	    dummy_shell=""
	    named_osrelease=0
	else
	    useradd_options="-M"
	    if [ -f /etc/mandrake-release ]; then
		linux_distr="mandrake"
	    elif [ -f /etc/fedora-release ]; then
		linux_distr="fedora"
	    elif [ -f /etc/SuSE-release ]; then
		linux_distr="suse"
		useradd_options="-r"
	    elif [ -f /etc/debian_version ]; then
		linux_distr="debian"
		get_domainname="dnsdomainname"
		useradd_options=""
	    else
		linux_distr="redhat"
	    fi

	    sndml_ini="/etc/init.d/sendmail"
	    mail_local="/usr/libexec/mail.local"
	    if [ -x /sbin/nologin ]; then
		dummy_shell="/sbin/nologin"
	    else
		dummy_shell="/bin/false"
	    fi
	    bash_shell="/bin/bash"
	    rbash_shell="/bin/rbash"
	    uudecode_full="/usr/bin/uudecode"
	    named_osrelease=`cat /proc/sys/kernel/osrelease | perl -F"/[.-]/" -n -a  -e 'printf "%02u%02u%02u\n", $F[0],$F[1],$F[2]'`
	fi

	return 0
}
### Copyright 1999-2013. Parallels IP Holdings GmbH. All Rights Reserved.

prog="`basename $0`"

usage()
{
	if [ -n "$*" ]; then
		echo "ERROR: $*" >&2
		echo >&2
	fi

cat << EOT
Usage: $prog --domain-name domain --sys-user-login user [--webspace-name webspace] [--defer sec] [--create] [--force]

    --domain-name    <domain>           Relink log files for specified domain.
    --sys-user-login <primary FTP user> Primary FTP system user login for specified domain.
    --webspace-name  <webspace>         Webspace name if specified domain is either subdomain or addon domain.
    --defer          <timeout in sec.>  Defer relinking logs for at least the given timeout.
    --create                            Create new logs directory if it doesn't exist yet.
    --force                             Force operation. If something obstructs it, it will be removed first.
    --help                              Show this help screen.
EOT
	exit 1
}

just_die()
{
	echo "ERROR: $*" >&2
	exit 3
}

# --- parse and check args ---

while [ "$#" -gt 0 ]; do
	case "$1" in
		--domain-name)
			opt_domain_name="$2"
			[ "$#" -ge 2 ] && shift 2 || break
			;;
		--sys-user-login)
			opt_sys_user_login="$2"
			[ "$#" -ge 2 ] && shift 2 || break
			;;
		--webspace-name)
			opt_webspace_name="$2"
			[ "$#" -ge 2 ] && shift 2 || break
			;;
		--defer)
			opt_defer="$2"
			[ "$#" -ge 2 ] && shift 2 || break
			;;
		--create)
			opt_create="yes"
			shift
			;;
		--force)
			opt_force="yes"
			shift
			;;
		-h|--help)
			usage
			;;
		*)
			usage "Unknown argument '$1'"
			;;
	esac
done

[ -n "$opt_domain_name" ] || usage "Missing required option --domain-name"
[ -n "$opt_sys_user_login" ] || usage "Missing required option --sys-user-login"
[ -z "$opt_defer" ] || [ "$opt_defer" -ge 0 ] 2>/dev/null || usage "Argument to --defer option is not a valid number"

# --- desired logs structure ---
#
#   0700  psaadm:root /var/www/vhosts/system/domain.tld/logs
#                       *                                                       ("real" logs)
#   0700  psaadm:root /var/www/vhosts/system/addon-domain.tld/logs
#   0700  psaadm:root /var/www/vhosts/system/subdomain.domain.tld/logs
#
#   0700 sysuser:root /var/www/vhosts/domain.tld/logs
#                       * -> /var/www/vhosts/system/domain.tld/logs/*           (hardlinks)
#   0700 sysuser:root /var/www/vhosts/domain.tld/logs/addon-domain.tld
#                       * -> /var/www/vhosts/system/addon-domain.tld/logs/*     (hardlinks)
#   0700 sysuser:root /var/www/vhosts/domain.tld/logs/subdomain.domain.tld
#                       * -> /var/www/vhosts/system/subdomain.domain.tld/logs/* (hardlinks)
#
# Please note that files in /var/www/vhosts/system/ are not altered or managed by this utility.
# 0700 sysuser:psacln access rights for user logs directories are also acceptable.
#

# --- worker functions ---

is_dir()
{
	local dir="$1"
	[ -d "$dir" -a ! -L "$dir" ]
}

relink_file()
{
	local source="$1"
	local target="$2"
	[ -n "$source" -a -n "$target" ] || return 2

	[ -n "$opt_force" ] && rm -rf "$target"
	ln -Tnf "$source" "$target"
}

ensure_target_dir_exists()
{
	local logs_d="$1"
	local expected_user="$2"
	[ -n "$logs_d" -a -n "$expected_user" ] || return 2

	if is_dir "$logs_d"; then
		local perms="`stat -c '%a' \"$logs_d\"`"
		local user="`stat -c '%U' \"$logs_d\"`"
		local group="`stat -c '%G' \"$logs_d\"`"

		# Since we require permissions to be 0700, allow recreating logs/ by user as well.
		if [ "0$perms" -eq 0700 -a "$user" = "$expected_user" -a \( "$group" = "root" -o "$group" = "psacln" \) ]; then
			return 0
		fi
	fi

	# here either access rights or file type is wrong
	if [ -n "$opt_create" ]; then
		[ -n "$opt_force" ] && rm -rf "$logs_d"
		mkdir -m 0700 "$logs_d" || return 1
		chown "$expected_user:root" "$logs_d"
		chmod 0700 "$logs_d"

		# This should have been in vhost skeleton
		#local readme_file="$logs_d/README"
		#[ -e "$readme_file" ] || generate_readme > "$readme_file"
		#chown "root:root" "$readme_file"
		#chmod 0644 "$readme_file"

		pp_echo "'$logs_d' was (re)created."
	elif [ -n "$opt_force" ] && is_dir "$logs_d"; then
		chown "$expected_user:root" "$logs_d"
		chmod 0700 "$logs_d"

		pp_echo "Access rights for '$logs_d' were reset."
	else
		if is_dir "$logs_d"; then
			pp_echo "'$logs_d' already exists, but has wrong access rights. Specify --force to override."
		elif [ -e "$logs_d" ]; then
			pp_echo "'$logs_d' exists, but has wrong type. Specify --create --force to override."
		else
			pp_echo "'$logs_d' doesn't exist. Specify --create to create."
		fi
		return 1
	fi

	return 0
}

real_dir_path()
{
	local rc=0
	local dir="$1"
	[ -n "$dir" -a -d "$dir" ] || return 1
	local cwd="`pwd`"

	cd "$dir" || return 1
	pwd -P; rc=$?
	cd "$cwd" || return 1
	return $rc
}

relink_dir()
{
	local src_logs_d="$1"
	local tgt_logs_d="$2"
	[ -n "$src_logs_d" ] && is_dir "$src_logs_d" || return 2
	[ -n "$tgt_logs_d" ] && is_dir "$tgt_logs_d" || return 2

	# paranoia ON
	local vhosts_d_real=
	vhosts_d_real="`real_dir_path \"$HTTPD_VHOSTS_D\"`" || return 1

	cd "$tgt_logs_d" || return 1

	local tgt_logs_d_real=
	tgt_logs_d_real="`pwd -P`" || return 1

	# Should be: $tgt_logs_d_real == $vhosts_d_real + $tail && $tgt_logs_d == $HTTPD_VHOSTS_D + $tail
	local tgt_logs_in_vhosts_d_path="${tgt_logs_d#$HTTPD_VHOSTS_D}"
	local tgt_logs_in_vhosts_d_path_real="${tgt_logs_d_real#$vhosts_d_real}"
	if [ "$tgt_logs_in_vhosts_d_path" != "$tgt_logs_in_vhosts_d_path_real" ]; then
		pp_echo "Path check failed. Will not relink '$tgt_logs_d'."
		return 1
	fi

	# Inodes should match
	local cwd_inode="`stat -c '%i' .`"
	local tgt_inode="`stat -c '%i' \"$tgt_logs_d\"`"
	if [ "$tgt_inode" != "$cwd_inode" ]; then
		pp_echo "Inode check failed. Will not relink '$tgt_logs_d'."
		return 1
	fi
	# paranoia OFF

	for log in `ls "$src_logs_d/" 2>/dev/null`; do
		relink_file "$src_logs_d/$log" "./$log" || pp_echo "Failed to relink '$src_logs_d/$log' to '$tgt_logs_d/$log', skipped."
	done
}

deferred()
{
	if [ -z "$opt_defer" ] || [ "$opt_defer" -le 0 ]; then
		"$@"
	else
		pp_echo "Logs will be relinked asynchronously in background after $opt_defer seconds."
		{
			sleep "$opt_defer"
			"$@" || pp_echo "Task '$@' failed with return code $?."
		} >> /tmp/plesk-relink-vhost-logs-async-task.log 2>&1 &
	fi
}

# --- the script ---

product_default_conf
initial_conf
set_common_params
read_conf
umask 022

# Don't defer relinking logs if requested delay more than 1 hour.
if [ -n "$opt_defer" ] && [ "$opt_defer" -ge "$(( 1 * 60 * 60 ))" ]; then
	pp_echo "Defer interval is too large. Logs will be automatically relinked right now and in 24 hours."
	opt_defer=
fi
# Otherwise add a number for the top of the head (e.g., 10 seconds) to allow web servers to restart.
if [ -n "$opt_defer" ]; then
	opt_defer="$(( $opt_defer + 10 ))"
fi

cd "$HTTPD_VHOSTS_D" || just_die "Cannot cd to '$HTTPD_VHOSTS_D'"

if [ -n "$opt_webspace_name" ]; then
	ensure_target_dir_exists "./$opt_webspace_name/logs" "$opt_sys_user_login" || 
		just_die "Cannot relink logs. Target directory '$HTTPD_VHOSTS_D/$opt_webspace_name/logs' is in invalid state."
	ensure_target_dir_exists "./$opt_webspace_name/logs/$opt_domain_name" "$opt_sys_user_login" || 
		just_die "Cannot relink logs. Target directory '$HTTPD_VHOSTS_D/$opt_webspace_name/logs/$opt_domain_name' is in invalid state."
	
	deferred relink_dir "$HTTPD_VHOSTS_D/system/$opt_domain_name/logs" "$HTTPD_VHOSTS_D/$opt_webspace_name/logs/$opt_domain_name"
else
	ensure_target_dir_exists "./$opt_domain_name/logs" "$opt_sys_user_login" || 
		just_die "Cannot relink logs. Target directory '$HTTPD_VHOSTS_D/$opt_domain_name/logs' is in invalid state."
	
	deferred relink_dir "$HTTPD_VHOSTS_D/system/$opt_domain_name/logs" "$HTTPD_VHOSTS_D/$opt_domain_name/logs"
fi

# vim:ft=sh:
