#!/bin/sh
# Copyright (c) 2003 by SWsoft Inc.
# All rights reserved
#
#ident  "@(#)plesk 6.0  05/02/03 BSG"

#
# Plesk PostgreSQL connection verify script
#

def_mode="644"

set_mod()
{
	perms="$1"
	node="$2"

	chmod $perms $node
}

p_echo()
{
	echo "$*"
}

pno_echo()
{
	return
}

pnnl_echo()
{
	if [ -z $necho_defined ]; then
		# set up echo
		case "`echo 'x\c'`" in
    		'x\c')
				echo="echo -n"
				nnl=
			;;
			x)
				echo="echo"
				nnl="\c"
			;;
			*)
				echo "Unable to set up echo."
			;;
		esac

		necho_defined=true
	fi

	$echo "$*${nnl}"
}

test_for_root()
{
	my_id="`id`"
	case "$my_id" in
		uid=0\(root\)*)
			;;
		*)	p_echo "This script must be run as root"
			echo 1
			exit 1
			;;
	esac
}

get_etc_conf()
{
	if [ ! -f $config ]; then
		p_echo "Unable to open $config file."
		echo 3
		exit 3
	fi

	config_text=`sed -e '/^#/d' -e '/^$/d' $config | awk '{print $1"="$2}'`
	eval $config_text

	product_root=$PRODUCT_ROOT_D
	if [ -z "$product_root" ]; then
		p_echo "Unable to define $product root directory."
		echo 3
		exit 3
	fi

	product_bin_dir=$product_root/admin/bin
	if [ ! -d "$product_bin_dir" ]; then
		p_echo "Unable to locate $product bin directory."
		echo 3
		exit 3
	fi

	mysql_bin_dir=$MYSQL_BIN_D
	if [ ! -d "$mysql_bin_dir" ]; then
		p_echo "Unable to locate $mysql_bin_dir bin directory."
		echo 3
		exit 3
	fi

	rc_dir=$PRODUCT_RC_D
	if [ -z "$rc_dir" ]; then
		rc_dir=$product_root/rc.d
	fi

	pg_bin_dir=$PGSQL_BIN_D
	if [ -z "$pg_bin_dir" ]; then
		p_echo "Unable to define $product PostgreSQL bin directory."
		echo 3
		exit 3
	fi

	pg_data_dir=$PGSQL_DATA_D
	if [ -z "$pg_data_dir" ]; then
		p_echo "Unable to define $product PostgreSQL var directory."
		echo 3
		exit 3
	fi

	if [ ! -z "`$product_bin_dir/packagemng psa | grep psa | awk -F : '{print $2}'`" -a \
		-z "`$product_bin_dir/packagemng postgresql-server | grep postgresql-server | awk -F : '{print $2}'`" ]; then
		p_echo "PostgreSQL is not installed."
		echo 3
		exit 3
	fi

	pg_real_ver="`$pg_bin_dir/psql --version | head -1 | awk '{print $3}' - | awk -F'.' '{print $1"."$2}' -`"
	case "$pg_real_ver" in
		7.[123])
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac
}

repair_connect()
{
	get_locale_connection_perm

	if [ -z "$local_connect_string" ]; then
		case "$pg_real_ver" in
			7.3)
				local_connect_string='local	template1	all	trust #Added by Plesk'
				;;
			7.[12])
				local_connect_string='local	all			trust'
				;;
			*)
				p_echo "Not supported PostgreSQL version is installed."
				echo 3
				exit 3
				;;
		esac

		(echo; echo "$local_connect_string") >> $pg_hba

		reread_conf_flag=1
		return 0
	fi

	if [ "X$local_connect_string" = "Xtrust" ]; then
		return 0
	fi

	case "$pg_real_ver" in
		7.3)
			connect_change_string_from='^[[:space:]]*local[[:space:]][[:space:]]*all\|template1[[:space:]][[:space:]]*all[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*.*$'
			connect_change_string_to='local	template1	all	trust #Added by Plesk'
			;;
		7.[12])
			connect_change_string_from='^[[:space:]]*local[[:space:]][[:space:]]*all[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*.*$'
			connect_change_string_to='local	all	trust'
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
	esac

	sed -e '/'"$connect_change_string_from"'/c \
'"$connect_change_string_to" $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	reread_conf_flag=1

	# If pg_ctl is called from within init.d/postgresql with -w option (SuSE by default)
	# it will try to connect to database and therefore asks the password... (26190)
	if [ -f '/etc/SuSE-release' -a -f '/etc/init.d/postgresql' ]; then
		perl -pi -e 's/^\s*pg_ctl start -s -w -p \$H -l \$LOGFILE -D \$DATADIR -o \"\\\"\$OPTIONS\\\"\"\s*$/\tpg_ctl start -s -p \$H -l \$LOGFILE -D \$DATADIR -o \"\\\"\$OPTIONS\\\"\" # Changed by Plesk\n/g' /etc/init.d/postgresql
	fi

	return 0
}

get_locale_connection_perm()
{
	# ... and formatting

	case "$pg_real_ver" in
		7.3)
			local_connect_string=`grep -e '^[[:space:]]*local[[:space:]][[:space:]]*all\|template1[[:space:]][[:space:]]*all[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*' $pg_hba | sed 's/^[[:space:]][[:space:]]*//;s/[[:space:]][[:space:]]*$//;s/[[:space:]][[:space:]]*/\ /g' | cut -d ' ' -f4`
			;;
		7.[12])
			local_connect_string=`grep -e '^[[:space:]]*local[[:space:]][[:space:]]*all[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*' $pg_hba | sed 's/^[[:space:]][[:space:]]*//;s/[[:space:]][[:space:]]*$//;s/[[:space:]][[:space:]]*/\ /g' | cut -d ' ' -f3`
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac

}

chk_psa_user_exists()
{
	if [ -z "$1" ]; then
		return $1
	fi

	user=$1

	query=`$psql -qtc "select * from pg_shadow where usename='$user'"`

	if [ -z "$query" ]; then
		return 1
	fi

	return 0
}

add_psa_local_connection()
{
	if [ -z "$1" ]; then
		return 1
	fi

	case "$pg_real_ver" in
		7.3)
			local_connect_message="\n$hba_psa_mess1\nlocal	template1	all		$1	#Added by Plesk\n$hba_psa_mess2"
			;;
		7.[12])
			local_connect_message="\n$hba_psa_mess1\nlocal	template1	$1\n$hba_psa_mess2"
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac

	# Trust connection add in begin after end of comments
	awk 'BEGIN{flag = 0} {if (!/^#/ && flag != 1) {print "'"$local_connect_message"'"; flag = 1;}; print $0;}' $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	add_trust_flag=1

	return 0
}

change_trust_local_connection()
{
	sed -e '/^[[:space:]]*local/s/trust/password/' $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	return
}

change_passwd_local_connection()
{
	sed -e '/^[[:space:]]*local/s/password/trust/' $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	return
}

remove_psa_local_connection()
{
	sed -e "/$hba_psa_mess1/,/$hba_psa_mess2/d" -e '/^$/d' $pg_hba  > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	return
}

remove_psa_mess()
{
	sed -e "/$hba_psa_mess1/d" -e "/$hba_psa_mess2/d" -e '/^$/d' $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	return
}

add_psa_login()
{
	if [ -z "$1" ] || [ -z "$2" ]; then
		return 1
	fi

	admin_login=$1
	admin_pass=$2

	$psql -c "CREATE USER \"$admin_login\" WITH PASSWORD '$admin_pass' CREATEDB CREATEUSER"

	return $?
}

ch_db_owner()
{
	if [ -z "$1" ] || [ -z "$2" ]; then
		return 1
	fi

	ch_db_old_login=$1
	ch_db_new_login=$2

	$psql -c "UPDATE pg_database set datdba=(SELECT usesysid from pg_shadow where usename='$ch_db_new_login') where datdba=(SELECT usesysid from pg_shadow where usename='$ch_db_old_login')"

	return $?
}

remove_psa_login()
{
	if [ -z "$1" ]; then
		return 1
	fi

	admin_login=$1

	ch_db_owner $admin_login 'postgres'
	$psql -c "DROP USER \"$admin_login\""

	return $?
}

ch_user_pass()
{
	if [ -z "$1" ] || [ -z "$2" ]; then
		return 1
	fi

	new_login=$1
	new_pass=$2

	$psql -c "ALTER USER $new_login WITH PASSWORD '$new_pass'"

	return 0
}

ch_admin_param()
{
	if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
		return 1
	fi

	old_login=$1
	new_login=$2
	new_pass=$3

	if [ "X$old_login" = "X$new_login" ]; then
		ch_user_pass $new_login $new_pass
		return 0
	fi

	if [ ! -z "$old_login" ]; then
		remove_psa_login $old_login
	fi

	add_psa_login $new_login $new_pass

	return 0
}

reread_conf()
{
	#Reread PostrgeSQL config (pg_hba.conf)
	if postmaster_run; then
		kill -HUP $PID
	fi
}

postmaster_run()
{
	proc_name="postmaster"

	case "$machine" in
		solaris)
			PID=`ps -ef | grep "$proc_name" | grep -v grep | awk '{print $2}'`
		;;
		*)
			PID=`ps axww | awk '$5 ~ "'$proc_name'$" {print $1}'`
		;;
		esac

	if [ -z "$PID" ]; then
		# PG is not running
		return 1
	fi

	return 0
}

postmaster_start()
{
	if ! postmaster_run; then
		$rc_dir/postgresql start >/dev/null 2>&1
		sleep 3

		POSTMASTER_STOP="stop_after_work"

		if ! postmaster_run; then
			echo "Unable to start PostgreSQL."
			echo 1
			exit 1
		fi
	fi
}

postmaster_stop()
{
	if postmaster_run; then
		$rc_dir/postgresql stop >/dev/null 2>&1

		if postmaster_run; then
			echo "Unable to stop PostgreSQL."
			echo 1
			exit 1
		fi
	fi
}

before_end()
{
	if [ ! -z "$add_trust_flag" ]; then
		remove_psa_local_connection
		reread_conf_flag=1
	fi

	if [ ! -z "$reread_conf_flag" ]; then
		reread_conf
	fi

	return
}

chk_db_rec_exists()
{
	if [ -z "$1" ]; then
		return 1
	fi

	get_db_file_name "$1"

	case "$pg_real_ver" in
		7.3)
			local_connect_message="^[[:space:]]*local[[:space:]][[:space:]]*"$db_name"[[:space:]][[:space:]]*@"$db_usrs_file_name"[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*"
			;;
		7.[12])
			local_connect_message="^[[:space:]]*local[[:space:]][[:space:]]*"$db_name"[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*[[:space:]][[:space:]]*$db_usrs_file_name"
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac

	grep -e "$local_connect_message" $pg_hba > /dev/null 2>&1

	return $?
}

get_db_file_name()
{
	db_usrs_file_name="usrs_$1"
}

create_db_acess_file()
{
	get_db_file_name "$1"

	if [ ! -z "$db_usrs_file_name" ]; then
		touch "$pg_data_dir/$db_usrs_file_name" &&
		set_mod $def_mode "$pg_data_dir/$db_usrs_file_name"
	fi

	return
}

remove_db_acess_file()
{
	get_db_file_name "$1"

	if [ ! -z "$db_usrs_file_name" ]; then
		rm -f "$pg_data_dir/$db_usrs_file_name"
	fi

	return
}

pgconf_add_db()
{
	db_name="$1"

	if chk_db_rec_exists "$db_name"; then
		return 1
	fi

	get_db_file_name "$1"

	case "$pg_real_ver" in
		7.3)
			local_connect_message="\nlocal	$db_name		@$db_usrs_file_name	password	#Added by Plesk\n"
			;;
		7.[12])
			local_connect_message="\nlocal	$db_name		password	$db_usrs_file_name\n"
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac

	# DB string add in begin after end of comments
	awk 'BEGIN{flag = 0} {if (!/^#/ && flag != 1) {print "'"$local_connect_message"'"; flag = 1;}; print $0;}' $pg_hba | grep -v '^$' > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	reread_conf_flag=1

	return 0
}

pgconf_rm_db()
{
	db_name="$1"

	get_db_file_name "$1"

	case "$pg_real_ver" in
		7.3)
			local_connect_message="^[[:space:]]*local[[:space:]][[:space:]]*"$db_name"[[:space:]][[:space:]]*@"$db_usrs_file_name"[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*"
			;;
		7.[12])
			local_connect_message="^[[:space:]]*local[[:space:]][[:space:]]*"$db_name"[[:space:]][[:space:]]*[[:alnum:]][[:alnum:]]*[[:space:]][[:space:]]*$db_usrs_file_name"
			;;
		*)
			p_echo "Not supported PostgreSQL version is installed."
			echo 3
			exit 3
			;;
    esac

	sed -e "/$local_connect_message/d" -e '/^$/d' $pg_hba > $pg_hba.tmp &&
	mv -f $pg_hba.tmp $pg_hba &&
	set_mod $def_mode $pg_hba

	reread_conf_flag=1

	return 0
}

add_usr_db_access()
{
	db_name=$1
	db_usr="$2"

	get_db_file_name "$db_name"

	users_file="$pg_data_dir/$db_usrs_file_name"

	echo $db_usr > "$users_file.tmp"
	$mysql_bin_dir/mysql -uadmin -p$admin_passwd -N -e "select login from db_users dbu, data_bases db where dbu.db_id=db.id and db.type='postgresql' and db.name='$db_name'" $product >> "$users_file.tmp"
	[ -f "$users_file" ] && cat "$users_file" >> "$users_file.tmp"
	grep -v '^$' "$users_file.tmp" | sort | uniq > "$users_file"
	set_mod $def_mode $users_file

	rm -f "$users_file.tmp"

	reread_conf_flag=1

	return
}

rm_usr_db_access()
{
	get_db_file_name "$1"

	db_usr="$2"
	users_file="$pg_data_dir/$db_usrs_file_name"

	sed -e "/^$db_usr$/d" -e '/^$/d' "$users_file" > "$users_file.tmp" &&
	mv -f "$users_file.tmp" $users_file
	set_mod $def_mode $users_file

	reread_conf_flag=1

	return
}

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
export PATH

my_name_0="`pwd`"
my_name_1="`basename ""$0""`"
my_name_2=`echo ""$0"" | sed -e "s/^\.\///"`
case "$?" in
	0)
		my_name="$my_name_2"
	;;
	1)
		my_name="$my_name_0"/"$my_name_2"
	;;
    *)
		echo "Unable to retrieve the script name."
		echo 1
		exit 1
	;;
esac

###!!!!!! GLOBAL VARIABLES !!!!!###
product="psa"
product_full="Plesk"

support_email="support@sw-soft.com"
sales_email="sales@sw-soft.com"

product_version="`echo "6.0.0" | awk '{print $1}' -| awk -F'.' '{print $1"."$2}' -`"
###!!!!!! end GLOBAL VARIABLES !!!!!###

#product_log="/tmp/${my_name_1}.log"
config="/etc/$product/$product.conf"

hba_psa_mess1="# === Added by Plesk server (begin) ==="
hba_psa_mess2="# === Added by Plesk server (end) ==="

test_for_root
get_etc_conf

pg_hba="$pg_data_dir/pg_hba.conf"
admin_passwd="`cat /etc/$product/.psa.shadow`"
psql="$pg_bin_dir/psql -U postgres -d template1"


#Action select
case "$1" in
	--status)
		if postmaster_run; then
			echo "is running"
		else
			echo "is stopped"
		fi
		;;

	--start)
		postmaster_start
		;;

	--stop)
		postmaster_stop
		;;

	--restart)
		postmaster_stop
		postmaster_start
		;;

	add_db_usr)
		if [ -z "$2" ] || [ -z "$3" ]; then
			echo "Usage: $0 add_db_usr db_name db_usr_login"
			echo 1
			exit 1
		fi

		db_name=$2
		db_usr_login=$3

		pgconf_add_db "$db_name"

		add_usr_db_access $db_name $db_usr_login

		reread_conf
		;;

	rm_db_usr)
		if [ -z "$2" ] || [ -z "$3" ]; then
			echo "Usage: $0 rm_db_usr db_name db_usr_login"
			echo 1
			exit 1
		fi

		db_name=$2
		db_usr_login=$3

		rm_usr_db_access $db_name $db_usr_login

		# Remove a PostgreSQL 7.3 database record as empty file containing user list results in error
		if [ "X$pg_real_ver" = "X7.3" ]; then
			get_db_file_name "$db_name"
			users_file="$pg_data_dir/$db_usrs_file_name"

			users_number=`cat "$users_file" | wc -l`
			if [ $users_number -eq 0 ]; then
				remove_db_acess_file $db_name
				pgconf_rm_db $db_name
			fi
		fi

		reread_conf
		;;

	add_db)
		if [ -z "$2" ]; then
			echo "Usage: $0 add_db db_name"
			echo 1
			exit 1
		fi

		db_name=$2

		create_db_acess_file $db_name

		# Not creating a PostgreSQL 7.3 database record as empty file containing user list results in error
		if [ "$pg_real_ver" != "7.3" ]; then
			if ! pgconf_add_db "$db_name"; then
				p_echo "DB string already exists in the configuration file."
				echo 3
				exit 3
			fi
		fi

		reread_conf
		;;

	rm_db)
		if [ -z "$2" ]; then
			echo "Usage: $0 rm_db db_name"
			echo 1
			exit 1
		fi

		db_name=$2

		remove_db_acess_file $db_name

		pgconf_rm_db $db_name

		reread_conf
		;;

	change_user)
		if [ -z "$2" ] || [ -z "$3" ]; then
			echo "Usage: $0 change_user old_login new_login (password must be defined in the environment variable PSA_PASSWORD)"
			echo 1
			exit 1
		fi

		old_login=$2
		new_login=$3
		new_pass=$PSA_PASSWORD

		if [ -z $new_pass ]; then
			echo "Variable PSA_PASSWORD is not defined."
			echo 1
			exit 1
		fi

		#Add trust connections to PostgreSQL and reread config
		postmaster_start
		add_psa_local_connection "trust"
		reread_conf

		if chk_psa_user_exists $new_login ; then
			echo "User already exists."
			before_end
			echo 1
			exit 1
		fi

		ch_admin_param "$old_login" "$new_login" "$new_pass"

		before_end
		if [ ! -z "$POSTMASTER_STOP" ]; then
			postmaster_stop
		fi
		;;

	create_user)
		if [ -z "$2" ]; then
			echo "Usage: $0 create_user login (password must be defined in environment variable PSA_PASSWORD)"
			echo 1
			exit 1
		fi

		new_login=$2
		new_pass=$PSA_PASSWORD

		if [ -z $new_pass ]; then
			echo "Variable PSA_PASSWORD is not defined."
			echo 1
			exit 1
		fi

		#Add trust connections to PostrgeSQL and reread config
		postmaster_start
		repair_connect
		reread_conf

		if chk_psa_user_exists $new_login ; then
			echo "User already exists."
			before_end
			echo 1
			exit 1
		fi

		add_psa_login $new_login $new_pass

		change_trust_local_connection
		before_end
		if [ ! -z "$POSTMASTER_STOP" ]; then
			postmaster_stop
		fi
		;;

	remove_user)
		if [ -z "$2" ]; then
			echo "Usage: $0 remove_user login"
			echo 1
			exit 1
		fi

		new_login=$2

		postmaster_start
		add_psa_local_connection "trust"
		reread_conf

		remove_psa_login $new_login

		before_end
		if [ ! -z "$POSTMASTER_STOP" ]; then
			postmaster_stop
		fi
		;;

	change_pass)

		if [ -z "$2" ]; then
			echo "Usage: $0 change_pass login (password must be defined in the environment variable PSA_PASSWORD)"
			echo 1
			exit 1
		fi

		new_login=$2
		new_pass=$PSA_PASSWORD

		if [ -z $new_pass ]; then
			echo "Variable PSA_PASSWORD is not defined."
			echo 1
			exit 1
		fi

		#Add trust connections to PostrgeSQL and reread config
		postmaster_start
		add_psa_local_connection "trust"
		reread_conf

		ch_user_pass $new_login $new_pass

		before_end
		if [ ! -z "$POSTMASTER_STOP" ]; then
			postmaster_stop
		fi
		;;

	*)
		echo "Usage: $0 change_pass | change_user | create_user | remove_user | add_db | rm_db | add_db_usr | rm_db_usr"
		echo 1
		exit 1
esac

echo 0
exit 0
