#!/bin/sh
#
# postgresql	This is the init script for starting up the PostgreSQL
#		server
#
# chkconfig:	345 84 25
#
# description:	Starts and stops the PostgreSQL backend daemon that handles \
#		all database requests.
#
# processname:	postmaster

cd /

# Source function library
. /etc/rc.d/init.d/functions

# Get network config
. /etc/sysconfig/network

PG_INIT_LOCALE=C

# Get service config
if [ -f /etc/sysconfig/postgresql ]; then
	. /etc/sysconfig/postgresql
else
	nls "Error: %s not found" /etc/sysconfig/postgresql
	nls " PostgreSQL can't be run."
	exit 1
fi

if [ ! "$PG_DB_CLUSTERS" ]; then
	nls "Error: PG_DB_CLUSTERS not found or is empty"
	nls " PostgreSQL can't be run."
	exit 1
fi

# Check that networking is up.
if is_yes "${NETWORKING}"; then
	if [ ! -f /var/lock/subsys/network -a "$1" != stop -a "$1" != status -a "$1" != init ]; then
		msg_network_down PostgreSQL
		exit 1
	fi
else
	exit 0
fi

action="$1"

# any db cluster as command line argument?
if [ $# -gt 1 ]; then
	shift
	# perform action for specified clusters only
	DB_CLUSTERS="$@"
else
	DB_CLUSTERS="$PG_DB_CLUSTERS"
fi

#
# Useful functions.
#

#
# check for postgresql status
#
# arguments:
# $1 - db cluster
#
# sets variables:
# PG_STATUS = running | not running
# PG_PID    = pid of postmaster process
#
pgstatus() {
	PG_STATUS="unknown"
	PG_PID="unknown"
	output=$(LC_ALL=C TMPDIR=/tmp su postgres -c "/usr/bin/pg_ctl -D $1 status")
	status=$?

	if [ $status -eq 1 ]; then
		PG_STATUS="not running"
	elif [ $status -eq 0 ]; then
		PG_STATUS="running"
        # or maybe grab it from postmaster.pid file?
		PG_PID=$(echo "$output" | awk '/PID: / { match($0, "PID: [0-9]+"); print substr($0,RSTART+5,RLENGTH-5) }')
	fi
}

#
# start postgresql and display appropriate messages
#
# arguments:
# $1 - db cluster
#
pgstart() {
	is_no "$RC_LOGGING" && fork=--fork
	msg_starting "PostgreSQL $1"
	daemon $fork --user postgres /usr/bin/pg_ctl -s -w -D $1 start
}

#
# check for running postgresql instances; if any instance is running then
# create subsys lock file
#
pgsubsys() {
	# check for every defined db cluster in sysconfig file
	for pgdir in $PG_DB_CLUSTERS; do
		pgstatus "$pgdir"
		if [ "$PG_STATUS" = "running" ]; then
			touch /var/lock/subsys/postgresql
			return
		fi
	done
	rm -f /var/lock/subsys/postgresql
}

#
# End of useful functions.
#

start() {
	for pgdir in $DB_CLUSTERS; do
		pgstatus "$pgdir"
		if [ "$PG_STATUS" = "running" ]; then
			# pg_ctl status can misinform us about postgresql status
			# so let's check if postmaster is really alive
			if ps -p "$PG_PID" >/dev/null; then
				msg_already_running "PostgreSQL $pgdir"
			else
				# pg_ctl has misinformed us about postgresql status;
				# remove pid file and run postgresql
				msg_not_running "PostgreSQL $pgdir"
				rm -f $pgdir/postmaster.pid
				pgstart "$pgdir"
			fi
		else
			pgstart "$pgdir"
		fi
	done
	pgsubsys
}

stop() {
	for pgdir in $DB_CLUSTERS; do
		pgstatus "$pgdir"
		if [ "$PG_STATUS" = "not running" ]; then
			msg_not_running "PostgreSQL $pgdir"
		else
			msg_stopping "PostgreSQL $pgdir"
			busy
			# is postgresql really alive?
			if ps -p "$PG_PID" >/dev/null; then
				TMPDIR=/tmp su postgres -c "/usr/bin/pg_ctl -w -D $pgdir stop -m fast 2>&1 >/dev/null"
				pgstatus "$pgdir"
				if [ "$PG_STATUS" != "not running" ]; then
					fail
				else
					ok
				fi
			else
				# postgresql is not really alive; pg_ctl misinformed us
				# about the status
				died
			fi
			rm -f $pgdir/postmaster.pid
		fi
	done
	pgsubsys
}

RETVAL=0
# See how we were called.
# Every action is performed for all given (all configured by default)
# db clusters.
case "$action" in
  start)
  	start
	;;
  stop)
  	stop
	;;
  status)
	for pgdir in $DB_CLUSTERS; do
		pgstatus "$pgdir"
		if [ "$PG_STATUS" = "running" ]; then
			show "PostgreSQL cluster %s, PID %s" "$pgdir" "$PG_PID"
			progress "$PG_STATUS"
		else
			show "PostgreSQL cluster %s" "$pgdir"
			progress "$PG_STATUS" "$CFAIL"
		fi
		echo
	done
	;;
  restart)
	stop
	start
	;;
  reload|force-reload|try-restart)
	if [ "$action" = "reload" ]; then
		# "reload" must not restart service - so let it reload only what's possible
		pgctlact="reload"
	else
		pgctlact="restart"
	fi
	for pgdir in $DB_CLUSTERS; do
		pgstatus "$pgdir"
		if [ "$PG_STATUS" = "not running" ]; then
			msg_not_running "PostgreSQL $pgdir"
			if [ "$action" != "try-restart" ]; then
				RETVAL=7
			fi
		else
			msg_reloading "PostgreSQL $pgdir"
			busy
			# is postgresql really alive?
			if ps -p "$PG_PID" >/dev/null; then
				TMPDIR=/tmp su postgres -c "/usr/bin/pg_ctl -D $pgdir $pgctlact 2>&1 >/dev/null"
					pgstatus "$pgdir"
				if [ "$PG_STATUS" = "running" ]; then
					ok
				else
					fail
				fi
			elif [ "$action" != "try-restart" ]; then
				# postgresql died and pg_ctl has misinformed us about
				# the status - i.e. service is actually not running
				RETVAL=7
			else
				# postgresql died and pg_ctl has misinformed us about
				# the status; remove pid file and start it again
				deltext; died
				rm -f $pgdir/postmaster.pid
				pgstart "$pgdir"
			fi
		fi
	done
	pgsubsys
	;;
  init)
	nls "Note: this is only simple init action for convenience."
	nls "If you want some non-standard options, consider using initdb(1)."
	echo
	for pgdir in $DB_CLUSTERS; do
		if [ -f $pgdir/PG_VERSION ]; then
			echo $(nls "Skipping existing cluster %s" "$pgdir")
		else
			echo $(nls "Initializing cluster %s" "$pgdir")
			mkdir -p $pgdir
			chmod 700 $pgdir
			chown postgres:postgres $pgdir
			LC_ALL=$PG_INIT_LOCALE TMPDIR=/tmp su postgres -s /bin/sh -c "initdb -E UNICODE -D $pgdir"
		fi
	done
	echo $(nls "REMEMBER to setup password for user \"postgres\"")'!'
	;;
  *)
	msg_usage "$0 {start|stop|init|restart|reload|force-reload|status}"
	exit 3
esac

exit $RETVAL
