#!/bin/sh
#
# $Id$

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"
datarootdir="/usr/share"
datadir="/usr/share"
config_dir="${datadir}/gfarm/config"
globus_location=""

spool_owner=_gfarmfs

PROGNAME=`basename $0`

PRIVATE_MODE=false

#
# 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

. $config_dir/config-gfarm.common

usage()
{
	echo >&2 "usage: $PROGNAME [--help] [--prefix prefix] [--confdir dir]"
	echo >&2 "	[-t|-T] [-f]"
	echo >&2 "	[-a arch] [-p port] [-h hostname] [-n ncpu] "
	echo >&2 "	[-l listen_address] [-S] [-N] spool_directory"
	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_plain_params()
{
	echo "prefix                 [--prefix]: $CONFIG_PREFIX"
	echo "confdir               [--confdir]: $CONFIG_ETC_DIR"
	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                        : $RC_GFSD"
	echo "gfarm client conf file           : $GFARM_CLIENT_CONF"
	if $PRIVATE_MODE; then
		echo "gfsd conf file                   : $GFARM_CONF"
		echo "usermap file                     : $USERMAP_FILE"
	fi
	echo "gfsd pid file                    : $GFSD_PID_FILE"

	sanity
	exit 0
}

display_script_params()
{
	echo "CONFIG_PREFIX=$CONFIG_PREFIX"
	echo "GFSD_HOSTNAME=$GFSD_HOSTNAME"
	echo "LISTEN_ADDRESS=$LISTEN_ADDRESS"
	echo "ARCH=$ARCH"
	echo "GFSD_PORT=$GFSD_PORT"
	echo "NCPU=$NCPU"
	echo "SPOOL_DIRECTORY=$SPOOL_DIRECTORY"
	echo "GFSD_RC=$RC_GFSD"
	echo "GFARM_CONF=$GFARM_CLIENT_CONF"
	if $PRIVATE_MODE; then
		echo "GFSD_CONF=$GFARM_CONF"
		echo "USERMAP_FILE=$USERMAP_FILE"
	fi
	echo "GFSD_PID_FILE=$GFSD_PID_FILE"

	sanity
	exit 0
}

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

	# set parameters
	  --prefix) shift; [ $# -ge 1 ] || usage
		CONFIG_PREFIX=$1
		;;
	  # only for gfarm2.conf, gfsd.conf and usermap
	  --confdir) shift; [ $# -ge 1 ] || usage
		CONFIG_ETC_DIR=$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)
		PARAMS_DISPLAY_STYLE=plain
		;;
	  -T)
		PARAMS_DISPLAY_STYLE=script
		;;
	  -*)
		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:=}
: ${LISTEN_ADDRESS:=""}
if [ -n "$LISTEN_ADDRESS" ]; then
	: ${GFSD_SERVICE_NAME:="gfsd-$LISTEN_ADDRESS"}
else
	: ${GFSD_SERVICE_NAME:="gfsd"}
fi

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

: ${START_SERVICE:=true}
: ${FORCE:=false}
: ${PARAMS_DISPLAY_STYLE:=none}

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

if [ X"$CONFIG_PREFIX" != X ]; then
	: ${GFARM_CONF_DIR:="$CONFIG_PREFIX/etc"}
else
	: ${GFARM_CONF_DIR:="$sysconfdir"}
fi
: ${CONFIG_ETC_DIR:=$GFARM_CONF_DIR}
: ${UNCONFIG_SCRIPT:="$GFARM_CONF_DIR/unconfig-gfsd.sh"}
: ${UNCONFIG_SCRIPT_IN:="$config_dir/unconfig-gfsd.sh.in"}
if $PRIVATE_MODE; then
	: ${GFARM_CONF:="$CONFIG_ETC_DIR/gfsd.conf"}
else
	: ${GFARM_CONF:="$CONFIG_ETC_DIR/gfarm2.conf"}
fi
: ${GFARM_CLIENT_CONF:="$CONFIG_ETC_DIR/gfarm2.conf"}
: ${USERMAP_FILE:="$CONFIG_ETC_DIR/usermap"}

: ${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"}
: ${RC_GFSD:="$RC_DIR/$GFSD_SERVICE_NAME"}

if [ -n "$LISTEN_ADDRESS" ]; then
	: ${SPOOL_DIRECTORY:="$CONFIG_PREFIX/var/gfarm-spool-$LISTEN_ADDRESS"}
	: ${GFSD_EXTRA_OPTIONS:=" -l $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_VAR:="$GFSD_SERVICE_NAME"}
fi
: ${GFSD_PID_FILE:="$RUN_DIR/${GFSD_SERVICE_NAME}.pid"}

# -t option; display parameters
[ $PARAMS_DISPLAY_STYLE != none ] && display_${PARAMS_DISPLAY_STYLE}_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@|$GFSD_SERVICE_NAME|g" \
	-e "s|@config_gfarm_gfsd_rc_var@|$RC_VAR|g" \
	-e "s|@config_gfarm_gfsd_pid_file@|$GFSD_PID_FILE|g" \
	-e "s|@config_gfarm_run_dir@|$RUN_DIR|g" \
	${1+"$@"} | config_sysdep
}

unconfig()
{
	sed \
	-e "s|@config_gfarm_prefix@|$prefix|g" \
	-e "s|@config_gfarm_datadir@|$datadir|g" \
	-e "s|@config_gfarm_spool_directory@|$SPOOL_DIRECTORY|g" \
	-e "s|@config_gfarm_rc_gfsd@|$RC_GFSD|g" \
	-e "s|@config_gfarm_gfsd_pid_file@|$GFSD_PID_FILE|g" \
	-e "s|@config_gfarm_gfarm_config@|$GFARM_CONF|g" \
	-e "s|@config_gfarm_gfarm_client_config@|$GFARM_CLIENT_CONF|g" \
	-e "s|@config_gfarm_gfarm_conf_dir@|$GFARM_CONF_DIR|g" \
	-e "s|@config_gfarm_config_prefix@|$CONFIG_PREFIX|g" \
        -e "s|@config_gfarm_private_mode@|$PRIVATE_MODE|g" \
	-e "s|@config_gfarm_usermap_file@|$USERMAP_FILE|g" \
	-e "s|@config_gfarm_gfsd_hostname@|$GFSD_HOSTNAME|g" \
	${1+"$@"}
}

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

[ -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 | grep '^uid=0(' >/dev/null; 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
create_run_script "$RC_GFSD"	config "$RC_GFSD_IN"
$PRIVATE_MODE || service_reg gfsd

mkcnf "$UNCONFIG_SCRIPT"	unconfig "$UNCONFIG_SCRIPT_IN"
chmod +x "$UNCONFIG_SCRIPT" || ABORT "cannot chmod +x $UNCONFIG_SCRIPT"

# update configuration file
# spool_check_level (default value)
grep -v "^# spool_check_level lost_found" $GFARM_CONF > /dev/null ||
(echo "# spool_check_level lost_found" >> $GFARM_CONF &&
 echo $GFARM_CONF: "updated (spool_check_level)" ||
 ABORT "$GFARM_CONF: cannot append spool_check_level statement")

if $PRIVATE_MODE; then
# only private mode

# gfhost
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 $GFSD_PID_FILE ]; then ctl=restart; else ctl=start; fi
	service_add $GFSD_SERVICE_NAME &&
		service_ctl $GFSD_SERVICE_NAME $ctl ||
		ABORT "failed to $ctl $GFSD_SERVICE_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
service_ctl -n $GFSD_SERVICE_NAME start
fi

exit 0
