#!/bin/sh
#
# $Id: config-gfsd.in 4180 2009-06-16 13:02:41Z tatebe $

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

${DEBUG:="false"} && set -xu

# Gfarm installation directory
prefix="/usr"
sysconfdir="/etc"
config_dir="${prefix}/share/gfarm/config"
globus_location=""

spool_owner=_gfarmfs

PROGNAME=`basename $0`

#
# check whether shell function does work or not.
#
BOURNE_SHELL="${BOURNE_SHELL-/bin/sh}"
if [ x"$1" = x--re-invoked ]; then
	# shell function works with this shell, remove --re-invoked option
	shift
elif "$BOURNE_SHELL" -c 'shellfunc() { exit 0; }; shellfunc' 2>/dev/null; then
	# shell function works
	:
else
	# Search other shell that supports shell functions
	for sh in ksh bash zsh sh ash bsh sh5; do
		set `IFS=:;
		 P="/bin:/usr/5bin:/usr/bin:/usr/local/bin:/usr/pkg/bin:$PATH";
		 echo $P`
		for dir
		do
			shell="$dir/$sh"
			if ( [ -f "$shell" ] || [ -f "$shell.exe" ] ) &&
				"$shell" -c 'shellfunc() { exit 0; };
					shellfunc' 2>/dev/null
			then
				BOURNE_SHELL="$shell" exec "$shell" "$0" \
					--re-invoked ${1+"$@"}
			fi
		done
	done
	echo "$PROGNAME: cannot find a shell which supports functions" >&2
	exit 1
fi

usage()
{
	echo >&2 "usage: $PROGNAME [--help] [--prefix prefix] [-t] [-f]"
	echo >&2 "	[-a arch] [-p port] [-h hostname] [-n ncpu] "
	echo >&2 "	[-l listen_address] [-S] [-N] spool_directory"
	exit 1
}

ABORT()
{
	[ $# -gt 0 ] && echo >&2 "${PROGNAME}: $@"
	echo >&2 "$PROGNAME failure"
	exit 1
}

sanity()
{
	rv=0
	if [ ! -x "$prefix/bin/gfhost" ]; then
		echo "ERROR: command not found: $prefix/bin/gfhost" >&2
		rv=1
	fi
	case $SPOOL_DIRECTORY in
	/*)	:;;
	*)	echo "ERROR: spool directory ($SPOOL_DIRECTORY) must be absolute path"
		rv=1;;
	esac
	return $rv
}

display_params()
{
	echo "prefix   [--prefix]: $CONFIG_PREFIX"
	echo "hostname       [-h]: $GFSD_HOSTNAME"
	echo "listen address [-l]: `if [ x$LISTEN_ADDRESS != x ]; then echo $LISTEN_ADDRESS; else echo '(all local IP addresses)'; fi`"
	echo "architecture   [-a]: $ARCH"
	echo "port           [-p]: $GFSD_PORT"
	echo "ncpu           [-n]: $NCPU"
	echo "spool directory    : $SPOOL_DIRECTORY"
	echo "rc script name     : $RC_DIR/$RC_NAME"

	sanity
	exit 0
}

while [ $# -gt 0 ] ; do
	case $1 in

	# set parameters
	  --prefix) shift; [ $# -ge 1 ] || usage
		CONFIG_PREFIX=$1
		;;
	  -a) shift; [ $# -ge 1 ] || usage
		ARCH=$1
		;;
	  -p) shift; [ $# -ge 1 ] || usage
		GFSD_PORT=$1
		;;
	  -h) shift; [ $# -ge 1 ] || usage
		GFSD_HOSTNAME=$1
		;;
	  -l) shift; [ $# -ge 1 ] || usage
		LISTEN_ADDRESS=$1
		;;
	  -n) shift; [ $# -ge 1 ] || usage
		NCPU=$1
		;;

	# control options
	  --help)
		usage
		;;
	  -S)
		PRIVATE_MODE=true
		;;
	  -N)
		START_SERVICE=false
		;;
	  -f)
		FORCE=true
		;;
	  -t)
		DISPLAY_PARAMS=true
		;;
	  -*)
		usage
		;;
	  *)
		break
		;;
	esac
	shift
done

case $# in
0)	:;; # see below
1)	SPOOL_DIRECTORY=$1;;
*)	usage;;
esac

. $prefix/share/gfarm/config/config-gfarm.sysdep

#
# default values
#

: ${CONFIG_PREFIX:=}

# NOTE: $CONFIG_PREFIX needs to be set before calling sysdep_defaults
# sysdep_defaults must set: $RC_DIR
sysdep_defaults

: ${PRIVATE_MODE:=false}
: ${START_SERVICE:=true}
: ${FORCE:=false}
: ${DISPLAY_PARAMS:=false}

: ${RUN_DIR:="$CONFIG_PREFIX/var/run"}

if [ X"$CONFIG_PREFIX" != X ]; then
	: ${GFARM_CONF_DIR:="$CONFIG_PREFIX/etc"}
else
	: ${GFARM_CONF_DIR:="$sysconfdir"}
fi
if $PRIVATE_MODE; then
	: ${GFARM_CONF:="$GFARM_CONF_DIR/gfsd.conf"}
else
	: ${GFARM_CONF:="$GFARM_CONF_DIR/gfarm2.conf"}
fi
: ${GFARM_CLIENT_CONF:="$GFARM_CONF_DIR/gfarm2.conf"}

: ${FQ_HOSTNAME:=`fq_hostname`}

: ${GFSD_HOSTNAME:="$FQ_HOSTNAME"}
[ X"$GFSD_HOSTNAME" = X ] && ABORT 'cannot determine gfsd hostname, please specify it by -h option'

if $PRIVATE_MODE; then
	: ${GFSD_PORT:="10600"}
else
	: ${GFSD_PORT:="600"}
fi
: ${NCPU:=`number_of_cpus`}
[ X"$NCPU" = X ] && ABORT 'cannot determine number of CPUs'

: ${ARCH:=`$prefix/bin/gfarm.arch.guess`}
[ X"$ARCH" = X ] && ABORT 'cannot determine the architecture of this machine'

: ${RC_GFSD_IN="$config_dir/gfsd.in"}

: ${LISTEN_ADDRESS:=""}

if [ -n "$LISTEN_ADDRESS" ]; then
	: ${SPOOL_DIRECTORY:="$CONFIG_PREFIX/var/gfarm-spool-$LISTEN_ADDRESS"}
	: ${GFSD_EXTRA_OPTIONS:=" -l $LISTEN_ADDRESS"}
	: ${RC_NAME:="gfsd-$LISTEN_ADDRESS"}
	# $RC_VAR will be used as a shell variable name on *BSD ports & pkgsrc,
	# thus, we only allow [0-9a-z_] as its value.
	: ${RC_VAR:="`echo gfsd_$LISTEN_ADDRESS | sed 's/[^0-9a-z_]/_/g'`"}
else
	: ${SPOOL_DIRECTORY:="$CONFIG_PREFIX/var/gfarm-spool"}
	: ${GFSD_EXTRA_OPTIONS:=""}
	: ${RC_NAME:="gfsd"}
	: ${RC_VAR:="$RC_NAME"}
fi

# -t option; display parameters
$DISPLAY_PARAMS && display_params

sanity || ABORT "aborted"

#########################################################################

config()
{
	sed \
	-e "s|@config_gfarm_prefix@|$prefix|g" \
	-e "s|@config_gfarm_globus_location@|${GLOBUS_LOCATION:-$globus_location}|g" \
	-e "s|@config_gfarm_gfarm_config@|$GFARM_CONF|g" \
	-e "s|@config_gfarm_gfsd_option@|-f $GFARM_CONF -h $GFSD_HOSTNAME -r $SPOOL_DIRECTORY$GFSD_EXTRA_OPTIONS|g" \
	-e "s|@config_gfarm_gfsd_rc_name@|$RC_NAME|g" \
	-e "s|@config_gfarm_gfsd_rc_var@|$RC_VAR|g" \
	-e "s|@config_gfarm_run_dir@|$RUN_DIR|g" \
	${1+"$@"} | config_sysdep
}

mkcnf()
{
	# local out

	out=$1
	shift
	if ${1+"$@"} >$out; then
		echo created $out
	else
		ABORT "cannot create $out"
	fi
}

mkscript()
{
	mkcnf ${1+"$@"}
	chmod +x "$1" || ABORT "cannot chmod +x $1"
}

delete_file_or_directory()
{
	# local p

	for p
	do
		[ -d "$p" ] && rmdir "$p" > /dev/null 2>&1
		# [ -e "$p" ] isn't portable. not supported by Solaris /bin/sh
		if ls -1d "$p" >/dev/null 2>&1; then
			if $FORCE; then
				rm -rf "$p"
				echo removed "$p"
			else
				ABORT "$p already exist"
			fi
		fi
	done
}

create_directory()
{
	# local d

	for d
	do
		[ -d "$d" ] && continue
		if mkdir -p "$d"; then
			echo created "$d"
		else
			ABORT "mkdir -p $d, failed"
		fi
	done
}

#########################################################################

[ -f $GFARM_CONF ] || ABORT "$GFARM_CONF: no such file"

create_directory $RC_DIR $RUN_DIR

# spool directory
# delete_file_or_directory $SPOOL_DIRECTORY # XXX keep this
create_directory $SPOOL_DIRECTORY
[ X"`ls -ld $SPOOL_DIRECTORY | awk '{print $1}'`" = X"drwx------" ] ||
	chmod 0700 $SPOOL_DIRECTORY ||
	ABORT "chmod 0700 $SPOOL_DIRECTORY, failed"
if [ `id -u` -eq 0 ]; then
	chown $spool_owner $SPOOL_DIRECTORY ||
	ABORT "chown $spool_owner $SPOOL_DIRECTORY, failed. User '$spool_owner' is needed"
fi

mkcnf_gfsd_sysdep

# create run scripts
mkscript $RC_DIR/$RC_NAME	config "$RC_GFSD_IN"

if $PRIVATE_MODE; then
# only private mode

# update configuration file
USERMAP_FILE="$GFARM_CONF_DIR/usermap"
[ -f $USERMAP_FILE ] || ABORT "$USERMAP_FILE: no such file"
grep -v "^local_user_map" $GFARM_CONF > $GFARM_CONF.tmp &&
echo local_user_map $USERMAP_FILE >> $GFARM_CONF.tmp &&
mv $GFARM_CONF.tmp $GFARM_CONF &&
echo $GFARM_CONF: updated ||
ABORT "$GFARM_CONF: cannot append local_user_map statements"

# gfhost
if [ -z "${GLOBUS_LOCATION-}" ] && [ -n "$globus_location" ] &&
   [ -f "$globus_location/etc/globus-user-env.sh" ]
then
	GLOBUS_LOCATION="$globus_location"
	export GLOBUS_LOCATION
	. "$GLOBUS_LOCATION/etc/globus-user-env.sh"
fi
if [ X"$CONFIG_PREFIX" != X ]; then
	GFARM_CONFIG_FILE="$GFARM_CLIENT_CONF"
	export GFARM_CONFIG_FILE
fi

if $FORCE; then
	"$prefix/bin/gfhost" -d $GFSD_HOSTNAME > /dev/null 2>&1
fi
"$prefix/bin/gfhost" -c -a $ARCH -p $GFSD_PORT -n $NCPU $GFSD_HOSTNAME &&
echo gfhost $GFSD_HOSTNAME: succeeded ||
echo >&2 "gfhost -c -a $ARCH -p $GFSD_PORT -n $NCPU $GFSD_HOSTNAME: failed"

if $START_SERVICE; then
	if [ -f $RUN_DIR/$RC_NAME.pid ]; then ctl=restart; else ctl=start; fi
	service_add $RC_NAME &&
		service_ctl $RC_NAME $ctl ||
		ABORT "failed to $ctl $RC_NAME"
fi
echo "$PROGNAME success"

else # non private mode

echo "$PROGNAME success"
echo
echo Please ask admin_user to register your host by the following command:
echo
echo "$prefix/bin/gfhost" -c -a $ARCH -p $GFSD_PORT -n $NCPU $GFSD_HOSTNAME
echo
echo After that, start gfsd by the following command as a root:
echo
# XXX FIXME should use "forcestart" instead of "start" on NetBSD and FreeBSD.
echo "$RC_DIR/$RC_NAME start"

fi
exit 0
