#!/bin/sh
#v12.0.12
export NOCOLOR=1
export distdir=${distdir:-"/usr/local/cbsd"}
globalconf="${distdir}/cbsd.conf";
MYLOCK="/tmp/initenv.lock"
MYDESC="Node re-initialization"
MYARG=""
MYOPTARG=""
CBSDMODULE="sys"

inter=1
first_init=1
initenv_modify_cbsd_homedir=1
pre_cbsd_cmd_path=
post_cbsd_cmd_path=

if [ ! -f "${globalconf}" ]; then
	${ECHO} "${N1_COLOR}no such conf file${N0_COLOR}";
	exit 1
fi

# help mode
if [ "$1" = "--help" -o "$1" = "--desc" ]; then
	# skip for 'cbsd help module=' filter?
	if [ -n "${CBSDMODULEONLY}" ]; then
		[ "${CBSDMODULEONLY}" != "${CBSDMODULE}" ] && exit 0
	fi
	echo "[${CBSDMODULE}] ${MYDESC}"
	exit 0
fi

if [ "$1" = "inter=0" ]; then
	inter=0
	shift
fi

if [ -n "${NOINTER}" ]; then
	inter=0
fi

if [ -n "${1}" -a -f "${1}" ]; then
	INITCFG="${1}"
	shift

	if [ ! -r ${INITCFG} ]; then
		echo "cbsd initenv: preseed config file not readable: ${INITCFG}"
	fi

	# extra-override params?
	if [ -n "${1}" ]; then
		CBSD_INITCFG_EXTRA="/tmp/initenv.extra.$$"
		truncate -s0 ${CBSD_INITCFG_EXTRA}
		for i in $*; do
			if [ "${i}" = "inter=0" ]; then
				inter=0
				shift
				continue
			fi
			shift
			echo "${i}" >> ${CBSD_INITCFG_EXTRA}
		done
	fi
fi

err() {
	exitval=$1
	shift
	echo "$*" 1>&2
	exit ${exitval}
}

# create and store directory ID for relevant to sharedfs dirs
make_fs_id()
{
	local _id _dir

	for i in jaildatadir jailsysdir jailrcconfdir dbdir; do
		_dir=
		eval _dir="\$${i}"
		if [ ! -r ${_dir}/dir.id ]; then
			[ -z "${_id}" ] && _id=$( ${HEAD_CMD} -c 30 /dev/random | ${UUENCODE_CMD} -m - | ${TAIL_CMD} -n 2 | ${HEAD_CMD} -n1 | ${TR_CMD} -d '\r\n=' | ${TR_CMD} "/" "x" )
			${ECHO} "${N1_COLOR} * write directory id: ${i}${N0_COLOR}"
			echo "${_id}" > ${_dir}/dir.id
		fi
	done
}

init_zfs_feat()
{
	local ZFS_CMD= _ret=0
	local _root_pool= _pool= _dirname=

	zfsfeat=0

	ZFS_CMD=$( ${WHICH_CMD} zfs 2>/dev/null )
	if [ -n "${ZFS_CMD}" ]; then
		_tmpval=0
		case "${platform}" in
			Linux)
				${GREP_CMD} -q "^zfs " /proc/modules > /dev/null 2>&1
				_tmpval=$?
				;;
			*)
				${KLDSTAT_CMD} -qm zfs >/dev/null 2>&1;
				_tmpval=$?
				;;
		esac

		if [ ${_tmpval} -eq 0 ]; then
			_pool=$( ${ZFS_CMD} get -Ho value name ${workdir} 2>/dev/null )
			_ret=$?
			if [ -n "${_pool}" -a ${_ret} -eq 0 ]; then
				zfsfeat=1
				_root_pool=$( ${ZFS_CMD} get -Ho value name / 2>/dev/null )
				_ret=$?
				if [ -n "${_root_pool}" -a ${_ret} -eq 0 ]; then
					# first run?
					if [ ! -d "${workdir}/var/db" ]; then
						if [ "${_pool}" = "${_root_pool}" ]; then
							_dirname=$( ${BASENAME_CMD} ${workdir} )
							_parent_pool=$( echo "${_root_pool}" | ${TR_CMD} "/" " " | ${AWK_CMD} '{printf $1}' )
							if [ "${inter}" != "0" ]; then
								echo
								echo "Error: on ZFS-based systems, the CBSD requires a separate dataset different from the root one (${_root_pool})."
								echo "Please create a separate dataset first, e.g.:"
								echo
								echo " ${ZFS_CMD} create -o mountpoint=${workdir} -o atime=off ${_parent_pool}/${_dirname}"
								echo
								echo "Then re-run: env workdir=${workdir} /usr/local/cbsd/sudoexec/initenv"
								exit 1
							else
								# We will do automatically
								${ZFS_CMD} create -o mountpoint=${workdir} -o atime=off ${_parent_pool}/${_dirname}
								_ret=$?
								if [ ${_ret} -eq 0 ]; then
									echo "CBSD pool created: ${ZFS_CMD} create -o mountpoint=${workdir} -o atime=off ${_parent_pool}/${_dirname}"
								else
									echo "CBSD pool create failed: ${ZFS_CMD} create -o mountpoint=${workdir} -o atime=off ${_parent_pool}/${_dirname}"
									echo "Error: on ZFS-based systems, the CBSD requires a separate dataset different from the root one (${_root_pool})."
									exit ${_ret}
								fi
							fi
						fi
					fi
				fi
			fi
		fi
	fi

	return 0
}

desc_question()
{
	local _DEFAULT
	local _DESC

	if [ "${inter}" = "0" ]; then
		eval answ=\$$1
		case "${1}" in
			nodeip)
				## INET6/INET4-only?
				[ "${answ}" = "auto" ] && answ="${CBSD_IP4}"
				;;
			stable)
				[ "${answ}" = "auto" ] && answ=0
				;;
		esac
		return 0
	fi

	eval _DEFAULT="\$${1}_default"
	eval _DESC="\$${1}_desc"

	case "$1" in
		"fbsdrepo")
			if [ "${platform}" = "Linux" ]; then
				answ=1
				return 0
			fi
			if getyesno "${1}: ${_DESC} for fetching base/kernel?"; then
				answ=1
			else
				answ=0
			fi
			return 0
			;;
		"hammerfeat")
			if getyesno "${1}: You are running on a HAMMERFS-based system. ${_DESC}"; then
				answ=1
			else
				answ=0
			fi
			return 0
			;;
		"jnameserver")
			${ECHO} "${BOLD}${1}: ${_DESC} (for jails resolv.conf), e.g.: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "$answ" ] && answ="${_DEFAULT}"
			return 0
			;;
		"mdtmp")
			#will be processed differently. temporary hide this
			#	${ECHO} "${BOLD}${1}: ${_DESC} ?(${_DEFAULT} mb default)${N0_COLOR}"
			#	${ECHO} "${N1_COLOR}This md disk will be used for temporary operation? 0 - for disable or N (in mb) for disk size e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			#	read answ
			#	[ -z "${answ}" ] && answ=0
			answ=0
			return 0
			;;
		"nat_enable")
			if ! getyesno "${1}: ${_DESC}?"; then
				answ=0
				return 0
			fi
			[ -z "$answ" ] && answ="${_DEFAULT}"
			answ=1
			return 0
			;;
		"nodename")
			${ECHO} "${BOLD}${1}: ${_DESC}: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "$answ" ] && answ="${_DEFAULT}"
			return 0
			;;
		"nodeip")
			${ECHO} "${BOLD}${1}: ${_DESC} (used for node interconnection), e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			## INET6/INET4-only?
			[ "${answ}" = "default" -o "${answ}" = "auto" ] && answ="${CBSD_IP4}"
			[ -z "$answ" ] && answ="${_DEFAULT}"
			return 0
			;;
		"nodeippool")
			${ECHO} "${BOLD}${1}: ${_DESC} (networks for jails)${N0_COLOR}"
			${ECHO} "${N1_COLOR}Hint: use space as delimiter for multiple networks, e.g.: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "$answ" ] && answ="${_DEFAULT}"
			return 0
			;;
		"parallel")
			if [ "${platform}" = "Linux" ]; then
				answ="${_DEFAULT}"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(0 - no parallel or positive value (in seconds) as timeout for next parallel sequence) e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"stable")
			if [ "${platform}" = "Linux" ]; then
				answ="${_DEFAULT}"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(STABLE_X instead of RELEASE_X_Y branch for base/kernel will be used), e.g.: ${N2_COLOR}${_DEFAULT} ${N1_COLOR}(use release)${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"statsd_bhyve_enable")
			if [ "${platform}" = "Linux" ]; then
				answ="0"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(EXPERIMENTAL FEATURE)? e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"statsd_jail_enable")
			if [ "${platform}" = "Linux" ]; then
				answ="0"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(EXPERIMENTAL FEATURE)? e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"statsd_hoster_enable")
			if [ "${platform}" = "Linux" ]; then
				answ="0"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(EXPERIMENTAL FEATURE)? e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"sqlreplica")
			if [ "${platform}" = "Linux" ]; then
				answ="0"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(0 - no replica, 1 - try to replicate all local events to remote nodes) e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"clustering")
			if [ "${platform}" = "Linux" ]; then
				answ="0"
				return 0
			fi
			${ECHO} "${BOLD}${1}: ${_DESC} ?${N0_COLOR}"
			${ECHO} "${N1_COLOR}(0 - no experimental clustering options, 1 - implement the stable ones) e.g: ${N2_COLOR}${_DEFAULT}${N0_COLOR}"
			read answ
			[ -z "${answ}" ] && answ="${_DEFAULT}"
			return 0
			;;
		"zfsfeat")
			if getyesno "${1}: You are running on a ZFS-based system. ${_DESC}"; then
				answ=1
			else
				answ=0
			fi
			return 0
			;;
		"preseedinit")
			if getyesno "${1}: ${_DESC}"; then
				answ=1
			else
				answ=0
			fi
			return 0
			;;
		"default_vs")
			if ! getyesno "${1}: ${_DESC}?"; then
				answ=0
				return 0
			fi
			[ -z "$answ" ] && answ="${_DEFAULT}"
			answ=1
			return 0
			;;
		*)
			return 1
			;;
	esac
}

# check for old install and if exist - execute pre scripts from upgrade directory
# setup pkg if no other cfg
phase0()
{
	local myversion cbsdd_enable cbsd_workdir

	first_init=1

	. ${distdir}/cbsd.conf
	newver="${myversion}"

	# touch must be in paths until phase1 generates <cmd>_CMD macros
	[ ! -f /etc/rc.conf ] && ${TOUCH_CMD} /etc/rc.conf
	[ -z "${cbsd_workdir}" ] && . /etc/rc.conf
	[ -z "${cbsd_workdir}" ] && return 0

	if [ -r "${cbsd_workdir}/nc.inventory" ]; then
		first_init=0
	else
		${ECHO} "${N1_COLOR}CBSD workdir first init: ${N2_COLOR}${cbsd_workdir}${N0_COLOR}"
	fi

	cbsdver=
	oldver=

	workdir="${cbsd_workdir}"
	[ -r "${inventory}" ] && . ${inventory}

	# can be empty in inventory, work-around
	if [ -z "${workdir}" ]; then
		workdir="${cbsd_workdir}"
		/usr/local/cbsd/misc/cbsdsysrc -qf ${inventory} workdir="${cbsd_workdir}" > /dev/null 2>&1
	fi

	[ -z "${cbsdver}" ] && cbsdver="unknown"
	if [ -r "${workdir}"/ver ]; then
		oldver=$( ${CAT_CMD} "${workdir}"/ver | ${AWK_CMD} '{printf $1}' )
	fi
	[ -z "${oldver}" ] && oldver="unknown"
}

phase0X()
{
	[ -z "${workdir}" ] && return 0
	[ ! -d "${workdir}" ] && return 0
	[ ! -r "${workdir}/var/db/local.sqlite" ] && return 0

	# sometimes we have workdir/DB but no cbsdsql, double check with 'phase0'
	[ ! -x ${miscdir}/sqlcli ] && return 0	# no build/first run?

	${ECHO} "${N1_COLOR}[Stage 0:${N2_COLOR} upgrading and migration data from ${oldver} to ${newver}${N1_COLOR}]${N0_COLOR}"

	# build-in backup script
	readconf initenv.conf
	if [ -n "${initenv_backup_bases}" -a "${initenv_backup_bases}" != "0" ]; then
		[ -r "${distdir}/upgrade/backup_db/pre-initenv-backup" ] && ${distdir}/upgrade/backup_db/pre-initenv-backup
	fi
	[ -d "${workdir}/upgrade" ] && env workdir="${workdir}" ${FIND_CMD} ${workdir}/upgrade/ -mindepth 1 -maxdepth 1 -type f -name pre-initenv-\* -exec {} \;
	[ -d "${distdir}/upgrade" ] && env workdir="${workdir}" ${FIND_CMD} ${distdir}/upgrade/ -mindepth 1 -maxdepth 1 -type f -name pre-patch-\* -exec {} \;
}

# execute post scripts from upgrade directory
phaseX()
{
	local myversion cbsdd_enable cbsd_workdir workdir
	${ECHO} "${N1_COLOR}[Stage X:${N2_COLOR} upgrading${N1_COLOR}]${N0_COLOR}"
	[ -d "${distdir}/upgrade" ] && env workdir="${workdir}" ${FIND_CMD} ${distdir}/upgrade/ -mindepth 1 -maxdepth 1 -type f -name post-patch-\* -exec {} \;
	[ -d "${workdir}/upgrade" ] && env workdir="${workdir}" ${FIND_CMD} ${workdir}/upgrade/ -mindepth 1 -maxdepth 1 -type f -name post-initenv-\* -exec {} \;
}

phase1()
{
	local cbsd_home _ret

	${ECHO} "${N1_COLOR}[Stage 1:${N2_COLOR} account & dir hier${N1_COLOR}]${N0_COLOR}"
	id ${cbsduser} > /dev/null 2>&1

	if [ $? -eq 1 ]; then
		echo "No such user ${cbsduser}. Please follow instruction at https://github.com/cbsd/cbsd/blob/develop/share/docs/general/cbsd_quickstart.md"
		echo "if you install not from the ports"
		exit 1
	fi

	case "${platform}" in
		Linux)
			cbsd_home=$( echo ~${cbsd} > /dev/null 2>&1 )
			[ "${cbsd_home}" != "${workdir}" ] && ${USERMOD_CMD} -d ${workdir} cbsd
			;;
		*)
			if [ "${initenv_modify_cbsd_homedir}" = "1" ]; then
				# check for correct homedir
				if [ ! -r /etc/master.passwd ]; then
					echo "no such /etc/master.passwd file"
					exit 1
				fi
				cbsd_home=$( ${GREP_CMD} ^cbsd /etc/master.passwd | ${CUT_CMD} -d : -f 9 )
				[ "${cbsd_home}" != "${workdir}" ] && ${PW_CMD} usermod ${cbsduser} -d ${workdir} >/dev/null 2>&1
			else
				initenv_modify_cbsd_homedir=0
			fi
	esac

	if [ ! -d "${workdir}" ]; then
		${MKDIR_CMD} -m 755 ${workdir}
		if [ $? -ne 0 ]; then
			echo "mkdir error: ${workdir}"
			exit 1
		fi
	fi

	# workdir extra validation: https://github.com/cbsd/cbsd/issues/777
	real_workdir=$( ${REALPATH_CMD} ${workdir} )
	if [ "${real_workdir}" != "${workdir}" ]; then
		echo "normalize workdir path: ${workdir} -> ${real_workdir}"
		workdir="${real_workdir}"
		cbsd_workdir="${real_workdir}"
		/usr/local/cbsd/misc/cbsdsysrc -qf ${inventory} workdir="${cbsd_workdir}" > /dev/null 2>&1
	fi

	# check ZFS root dataset vs CBSD dataset
	init_zfs_feat

	printf "${myversion}" > ${workdir}/ver

	$ECHO "${N1_COLOR} * Check hier and permission..."

	${miscdir}/mtree ${workdir}

	if [ -n "${PRE_CBSD_CMD_PATH}" ]; then
		pre_cbsd_cmd_path="${PRE_CBSD_CMD_PATH}"
	fi
	if [ -n "${POST_CBSD_CMD_PATH}" ]; then
		post_cbsd_cmd_path="${POST_CBSD_CMD_PATH}"
	fi

	env PRE_CBSD_CMD_PATH="${pre_cbsd_cmd_path}" POST_CBSD_CMD_PATH="${post_cbsd_cmd_path}" workdir=${workdir} ${distdir}/misc/cmdboot
	_ret=$?
	if [ ${_ret} -ne 0 ]; then
		[ -r ${workdir}/cmd.subr ] && rm -f ${workdir}/cmd.subr
		echo "initenv cmdboot error: missing necessary binaries"
		exit 1
	fi
	# re-read cmd.subr

	if [ ! -r ${workdir}/cmd.subr ]; then
		echo "initenv cmdboot error: no sch cmd.subr, please check command: env workdir=${workdir} ${distdir}/misc/cmdboot"
		exit 1
	fi

	unset _CBSD_CMD_SUBR
	. ${workdir}/cmd.subr
	make_fs_id
	printf "${N0_COLOR}"

#	if [ -z "${clustering_enabled}" ]; then
#		desc_question clustering
#		clustering_enabled=${answ}
#	fi
#	cbsd_initenv_clustering_enabled=${clustering_enabled}
	cbsd_initenv_clustering_enabled=0
}

compile_cc()
{
	CC_CMD=$( ${WHICH_CMD} cc 2>/dev/null )
	if [ -z "${CC_CMD}" ]; then
		echo "error: non-binary distribution. You need the 'cc' compiler to finish preparing the cbsd"
		echo "please install 'clang' or 'gcc'"
		exit 0
	fi

	${CC_CMD} $*
}

phase2()
{
	local _dir _ldir _rdir _file _dirhier _d _pkgconf
	local _sudoers_dir=

	${ECHO} "${N1_COLOR}[Stage 2: ${N2_COLOR}build tools${N1_COLOR}]${N0_COLOR}"

	if [ "${cbsd_initenv_clustering_enabled}" = "1" ]; then
		echo "Clustering modus enabled, building Redis, Influx and DBI connectors!"
		mod_cbsd_redis_enabled=YES
		mod_cbsd_influx_enabled=YES
		mod_cbsd_dbi_enabled=YES
	fi

	[ ! -f "${distdir}/bin/cbsdsftp" ] && compile_cc ${distdir}/bin/src/cbsdsftp.c -o ${distdir}/bin/cbsdsftp -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdsftp6" ] && compile_cc ${distdir}/bin/src/cbsdsftp6.c -o ${distdir}/bin/cbsdsftp6 -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdssh" ] && compile_cc ${distdir}/bin/src/cbsdssh.c -o ${distdir}/bin/cbsdssh -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdssh6" ] && compile_cc ${distdir}/bin/src/cbsdssh6.c -o ${distdir}/bin/cbsdssh6 -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/sbin/netmask" ] && compile_cc ${distdir}/sbin/src/netmask.c -o ${distdir}/sbin/netmask
	[ ! -f "${distdir}/bin/cfetch" ] && compile_cc ${distdir}/bin/src/cfetch.c -o ${distdir}/bin/cfetch -lcurl -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/misc/jexec_env" ] && compile_cc ${distdir}/misc/src/jexec_env.c -o ${distdir}/misc/jexec_env
	[ ! -f "${distdir}/misc/jail_env" ] && compile_cc ${distdir}/misc/src/jail_env.c -o ${distdir}/misc/jail_env
	[ ! -f "${distdir}/misc/getshell" ] && compile_cc ${distdir}/misc/src/getshell.c -o ${distdir}/misc/getshell

	if [ ! -f "${distdir}/misc/sqlcli" ]; then
		_pkgconf=$( ${WHICH_CMD} pkg-config )
		if [ $? -ne 0 -o -z "${_pkgconf}" ]; then
			echo "pkg-config must be present on the system to build CBSD from the source. Please install it first: pkg install pkgconf";
			exit 1
		fi
		compile_cc ${distdir}/misc/src/sqlcli.c $( pkg-config sqlite3 --cflags --libs ) -lm -o ${distdir}/misc/sqlcli
	fi

	case "${platform}" in
		Linux)
			true
			[ ! -f "${distdir}/misc/conv2human" ] && compile_cc -DWITH_BSD_H -I/usr/local/include -I/usr/local/include/libelf -L/usr/local/lib ${distdir}/misc/src/conv2human.c -lelf -lutil -lbsd -o ${distdir}/misc/conv2human
			[ ! -f "${distdir}/misc/cbsd_fwatch" ] && compile_cc ${distdir}/misc/src/cbsd_lwatch.c -o ${distdir}/misc/cbsd_fwatch
			# not supported yet
			;;
		*)
			[ ! -f "${distdir}/misc/pwcrypt" ] && compile_cc ${distdir}/misc/src/pwcrypt.c -lcrypt -o ${distdir}/misc/pwcrypt
			[ ! -f "${distdir}/misc/elf_tables" ] && compile_cc -I/usr/local/include -I/usr/local/include/libelf -L/usr/local/lib ${distdir}/misc/src/elf_tables.c -lelf -o ${distdir}/misc/elf_tables
			[ ! -f "${distdir}/misc/fmagic" ] && compile_cc ${distdir}/misc/src/fmagic.c -lmagic -o ${distdir}/misc/fmagic
			[ ! -f "${distdir}/misc/cbsd_fwatch" ] && compile_cc ${distdir}/misc/src/cbsd_fwatch.c -o ${distdir}/misc/cbsd_fwatch
			[ ! -f "${distdir}/misc/cbsd_dot" ] && compile_cc ${distdir}/misc/src/cbsd_dot.c -o ${distdir}/misc/cbsd_dot
			[ ! -f "${distdir}/misc/chk_arp_byip" ] && compile_cc ${distdir}/misc/src/chk_arp_byip.c -o ${distdir}/misc/chk_arp_byip
			[ ! -f "${distdir}/misc/resolv" ] && compile_cc ${distdir}/misc/src/resolv.c -o ${distdir}/misc/resolv
			[ ! -f "${distdir}/misc/daemon" ] && compile_cc ${distdir}/misc/src/daemon.c -lutil -o ${distdir}/misc/daemon
			[ ! -f "${distdir}/misc/conv2human" ] && compile_cc -I/usr/local/include -I/usr/local/include/libelf -L/usr/local/lib ${distdir}/misc/src/conv2human.c -lelf -lutil -o ${distdir}/misc/conv2human
			;;
	esac

	arch=$( uname -m )
	[ "${arch}" = "x86_64" ] && arch="amd64"
	if [ "${arch}" = "i386" -o "${arch}" = "amd64" ]; then
		[ ! -f "${distdir}/misc/popcnttest" ] && compile_cc ${distdir}/misc/src/popcnttest.c -o ${distdir}/misc/popcnttest -msse4.2 > /dev/null 2>&1 || true
	fi
	[ ! -f "${distdir}/misc/efivar" ] && compile_cc ${distdir}/misc/src/efivar.c -o ${distdir}/misc/efivar
	[ ! -f "${distdir}/misc/cbsdtee" ] && compile_cc ${distdir}/misc/src/cbsdtee.c -o ${distdir}/misc/cbsdtee
	[ ! -f "${distdir}/tools/imghelper" ] && compile_cc ${distdir}/tools/src/imghelper.c -o ${distdir}/tools/imghelper
	[ ! -f "${distdir}/misc/cbsdlogtail" ] && compile_cc ${distdir}/misc/src/cbsdlogtail.c -o ${distdir}/misc/cbsdlogtail
	[ ! -f "${distdir}/misc/daemonize" ] && compile_cc ${distdir}/misc/src/daemonize/daemonize.c ${distdir}/misc/src/daemonize/getopt.c -I${distdir}/misc/src/daemonize -O2 -o ${distdir}/misc/daemonize

	case "${platform}" in
		DragonFly|Linux)
			true
			# not supported yet
			;;
		*)
			if [ "${cbsd_initenv_clustering_enabled}" = "1" ]; then
				[ ! -f ${distdir}/tools/racct-jail-statsd ] && compile_cc ${distdir}/tools/src/racct-jail-statsd.c ${distdir}/bin/cbsdsh/contrib/ini.c -lcurl -lpthread -DWITH_INFLUX ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lprocstat -ljail -lsqlite3 -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-jail-statsd
				[ ! -f ${distdir}/tools/racct-bhyve-statsd ] && compile_cc ${distdir}/tools/src/racct-bhyve-statsd.c ${distdir}/bin/cbsdsh/contrib/ini.c -lcurl -DWITH_INFLUX ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lprocstat -ljail -lsqlite3 -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-bhyve-statsd
				[ ! -f ${distdir}/tools/racct-hoster-statsd ] && compile_cc ${distdir}/tools/src/racct-hoster-statsd.c ${distdir}/bin/cbsdsh/contrib/ini.c ${distdir}/bin/cbsdsh/cbsdredis.c ${distdir}/bin/cbsdsh/contrib/credis.c -DWITH_REDIS -lcurl -DWITH_INFLUX ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lprocstat -ljail -lsqlite3 -lpthread -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-hoster-statsd
			else
				[ ! -f "${distdir}/tools/racct-jail-statsd" ] && compile_cc ${distdir}/tools/src/racct-jail-statsd.c ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lpthread -lprocstat -ljail -lsqlite3 -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-jail-statsd
				[ ! -f "${distdir}/tools/racct-bhyve-statsd" ] && compile_cc ${distdir}/tools/src/racct-bhyve-statsd.c ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lprocstat -ljail -lsqlite3 -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-bhyve-statsd
				[ ! -f "${distdir}/tools/racct-hoster-statsd" ] && compile_cc ${distdir}/tools/src/racct-hoster-statsd.c ${distdir}/lib/beanstalk-client/beanstalk.c -g -O0 -lutil -lprocstat -ljail -lsqlite3 -lpthread -I/usr/local/include -I${distdir}/lib/beanstalk-client -L/usr/local/lib -o ${distdir}/tools/racct-hoster-statsd
			fi
	esac

	[ ! -f "${distdir}/tools/select_jail" ] && compile_cc ${distdir}/tools/src/select_jail.c -o ${distdir}/tools/select_jail

	if [ ! -f ${distdir}/misc/dump_cpu_topology ]; then
		compile_cc -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/misc/src/dump_cpu_topology.c -o ${distdir}/misc/src/dump_cpu_topology.o
		compile_cc -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/lib/simplexml/simplexml.c -o ${distdir}/lib/simplexml/simplexml.o
		compile_cc -g -o ${distdir}/misc/dump_cpu_topology ${distdir}/misc/src/dump_cpu_topology.o ${distdir}/lib/simplexml/simplexml.o
		${RM_CMD} -f ${distdir}/misc/src/dump_cpu_topology.o ${distdir}/lib/simplexml/simplexml.o
	fi

	if [ ! -f ${distdir}/misc/dump_iscsi_discovery ]; then
		compile_cc -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/misc/src/dump_iscsi_discovery.c -o ${distdir}/misc/src/dump_iscsi_discovery.o
		compile_cc -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/lib/simplexml/simplexml.c -o ${distdir}/lib/simplexml/simplexml.o
		compile_cc -g -o ${distdir}/misc/dump_iscsi_discovery ${distdir}/misc/src/dump_iscsi_discovery.o ${distdir}/lib/simplexml/simplexml.o
		${RM_CMD} -f ${distdir}/misc/src/dump_iscsi_discovery.o ${distdir}/lib/simplexml/simplexml.o
	fi
	# todo: embed version to build and ask/check version before build

	if [ ! -r ${distdir}/misc/sipcalc ]; then
		if [ ! -x ${distdir}/misc/sipcalc5 ]; then
			if [ -f ${distdir}/misc/src/sipcalc/Makefile ]; then
				make -C ${distdir}/misc/src/sipcalc
				installne "-o ${cbsduser} -g ${cbsduser} -m 555 -s" ${distdir}/misc/src/sipcalc/sipcalc ${distdir}/misc/sipcalc
				make -C ${distdir}/misc/src/sipcalc clean
			fi
		fi
	fi

	if [ -f ${distdir}/misc/src/cbsd_md5/Makefile ]; then
		if [ ! -x ${distdir}/misc/cbsd_md5 ]; then
			make -C ${distdir}/misc/src/cbsd_md5
			installne "-o ${cbsduser} -g ${cbsduser} -m 555 -s" ${distdir}/misc/src/cbsd_md5/cbsd_md5 ${distdir}/misc/cbsd_md5
			make -C ${distdir}/misc/src/cbsd_md5 clean
		fi
	fi

	if [ ! -f ${distdir}/misc/ipv6range ]; then
		compile_cc -o ${distdir}/misc/ipv6range ${distdir}/misc/src/ipv6range.c
	fi
	case "${platform}" in
		DragonFly|Linux)
			true
			;;
		*)
			[ ! -f "${distdir}/misc/next-vale-port" ] && compile_cc -o ${distdir}/misc/next-vale-port ${distdir}/misc/src/next-vale-port.c
			[ ! -f "${distdir}/tools/vale-ctl" ] && compile_cc ${distdir}/tools/src/vale-ctl.c -o ${distdir}/tools/vale-ctl
			[ ! -f "${distdir}/tools/nic_info" ] && compile_cc ${distdir}/tools/src/nic_info.c -o ${distdir}/tools/nic_info
			[ ! -f "${distdir}/tools/bridge" ] && compile_cc ${distdir}/tools/src/bridge.c -o ${distdir}/tools/bridge
			;;
	esac
	if [ ! -x "/usr/local/bin/cbsd" ]; then
		_build_options=""
		[ "${mod_cbsd_redis_enabled}" = "YES" ] && _build_options="${_build_options} -DWITH_REDIS"
		[ "${mod_cbsd_influx_enabled}" = "YES" ] && _build_options="${_build_options} -DWITH_INFLUX"
		[ "${mod_cbsd_dbi_enabled}" = "YES" ] && _build_options="${_build_options} -DWITH_DBI"

		make -C ${distdir}/bin/cbsdsh clean && make ${_build_options} -DCBSDVERSION="${ncver}" -C ${distdir}/bin/cbsdsh
		# force rebuild sqlscli too to avoid possible SQLite3 link error
		compile_cc ${distdir}/misc/src/sqlcli.c -lsqlite3 -L/usr/local/lib -I/usr/local/include -o ${distdir}/misc/sqlcli
		[ -f "${distdir}/bin/cbsdsh/cbsd" ] && ${INSTALL_CMD} -m 0550 -s -o ${cbsduser} -g ${cbsduser} -m 550 ${distdir}/bin/cbsdsh/cbsd /usr/local/bin/cbsd
	fi
	${CHOWN_CMD} ${cbsduser}:${cbsduser} /usr/local/bin/cbsd
	${CHMOD_CMD} 0550 /usr/local/bin/cbsd

	#### /bin/cp SCRIPTS with override and readonly
	_dirhier="etc/defaults"

	for _d in ${_dirhier}; do
		_ldir="${workdir}/${_d}"
		_rdir="${distdir}/${_d}"
		for _file in $( ${FIND_CMD} ${_rdir} -mindepth 1 -maxdepth 1 -type f -exec ${BASENAME_CMD} {} \; ); do
			installne "-o ${cbsduser} -g ${cbsduser} -m 444" ${_rdir}/${_file} ${_ldir}/${_file}
		done
	done

	#### /bin/cp SCRIPTS without override
	_dirhier="share/helpers \
share/examples \
share/bsdconfig \
share/autocompletion \
share/emulators \
etc"

	${CAT_CMD} > ${etcdir}/cbsd_sudoers <<EOF
Defaults     env_keep += "workdir DIALOG NOCOLOR CBSD_RNODE"
Cmnd_Alias   CBSD_CMD = ${sudoexecdir}/*
${cbsduser}   ALL=(ALL) NOPASSWD:SETENV: CBSD_CMD
EOF

	for _d in ${_dirhier}; do
		_ldir="${workdir}/${_d}"
		_rdir="${distdir}/${_d}"
		for _file in $( ${FIND_CMD} ${_rdir} -mindepth 1 -maxdepth 1 -type f -exec ${BASENAME_CMD} {} \; ); do
			if [ ! -f "${_ldir}/${_file}" ]; then
				[ ! -d ${_ldir} ] && ${MKDIR_CMD} -p ${_ldir}
				${INSTALL_CMD} -o ${cbsduser} -g ${cbsduser} -m 444 ${_rdir}/${_file} ${_ldir}/${_file}
			fi
		done
	done

	#here is file with overwriting
	installne "-o ${cbsduser} -g ${cbsduser} -m 444" ${distdir}/share/DragonFly-git_branches.conf ${sharedir}/DragonFly-git_branches.conf
	installne "-o ${cbsduser} -g ${cbsduser} -m 444" ${distdir}/share/FreeBSD-git_branches.conf ${sharedir}/FreeBSD-git_branches.conf
	installne "-o ${cbsduser} -g ${cbsduser} -m 444" ${distdir}/share/HardenedBSD-git_branches.conf ${sharedir}/HardenedBSD-git_branches.conf
	installne "-o ${cbsduser} -g ${cbsduser} -m 444" ${distdir}/etc/Makefile ${etcdir}/Makefile

	case "${platform}" in
		Linux)
			_sudoers_dir="/etc/sudoers.d"
			;;
		*)
			_sudoers_dir="/usr/local/etc/sudoers.d"
			;;
	esac

	# 10_cbsd_sudoers for compatible with puppet sudo module
	if [ ! -f "${_sudoers_dir}/cbsd_sudoers" -a ! -f "${_sudoers_dir}/10_cbsd_sudoers" ]; then
		if getyesno "Shall I add the cbsd user into ${_sudoers_dir} sudo file to obtain root privileges for most of the cbsd commands?" ${initenv_modify_sudoers}; then
			initenv_modify_sudoers=1
			[ ! -d ${_sudoers_dir} ] && ${MKDIR_CMD} -p ${_sudoers_dir}
			installne "-o root -g 0 -m 440" ${etcdir}/cbsd_sudoers ${_sudoers_dir}/10_cbsd_sudoers
		fi
		initenv_modify_sudoers=0
	fi

	#    [ -d ${sshdir} ] || ${MKDIR_CMD} -m 0700 ${sshdir}
	#    [ -d "${sshdir}/sockets" ] || ${MKDIR_CMD} -m 0700 "${sshdir}/sockets"
	[ -f "${sshdir}/config" ] || installne "-o ${cbsduser} -g ${cbsduser} -m 640" ${distdir}/.ssh/config ${sshdir}/config

	# workaround for move jail-skel hier in cbsd 10.0.0
	[ ! -d "${sharedir}/${platform}-jail-skel/etc" -a -d "${distdir}/share/${platform}-jail-skel" ] && ${MKDIR_CMD} -p ${sharedir}/${platform}-jail-skel && /bin/cp -a ${distdir}/share/${platform}-jail-skel/* ${sharedir}/${platform}-jail-skel/
	[ -f "${sharedir}/${platform}-jail-skel/etc/master.passwd" ] && chmod 0600 ${sharedir}/${platform}-jail-skel/etc/master.passwd ${sharedir}/${platform}-jail-skel/etc/spwd.db

	# workaround for move jail-skel hier in cbsd 10.0.0
	[ ! -d "${sharedir}/${platform}-jail-vnet-skel/etc" -a -d "${distdir}/share/${platform}-jail-vnet-skel" ] && ${MKDIR_CMD} -p ${sharedir}/${platform}-jail-vnet-skel && /bin/cp -a ${distdir}/share/${platform}-jail-vnet-skel/* ${sharedir}/${platform}-jail-vnet-skel/
	[ -f "${sharedir}/${platform}-jail-vnet-skel/etc/master.passwd" ] && chmod 0600 ${sharedir}/${platform}-jail-vnet-skel/etc/master.passwd ${sharedir}/${platform}-jail-vnet-skel/etc/spwd.db

	[ ! -d "${sharedir}/${platform}-jail-puppet-skel/etc" -a -d "${distdir}/share/${platform}-jail-puppet-skel" ] && ${MKDIR_CMD} -p ${sharedir}/${platform}-jail-puppet-skel && /bin/cp -a ${distdir}/share/${platform}-jail-puppet-skel/* ${sharedir}/${platform}-jail-puppet-skel/
	[ -f "${sharedir}/${platform}-jail-puppet-skel/etc/master.passwd" ] && chmod 0600 ${sharedir}/${platform}-jail-puppet-skel/etc/master.passwd ${sharedir}/${platform}-jail-puppet-skel/etc/spwd.db

#	if [ ! -f "${sharedir}/${platform}-jail-kfreebsd-wheezy-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-kfreebsd-wheezy-system-skel" ]; then
#		${MKDIR_CMD} -p ${sharedir}/${platform}-jail-kfreebsd-wheezy-system-skel > /dev/null 2>&1
#		/bin/cp -a ${distdir}/share/${platform}-jail-kfreebsd-wheezy-system-skel/* ${sharedir}/${platform}-jail-kfreebsd-wheezy-system-skel/
#	fi
#	if [ ! -f "${sharedir}/${platform}-jail-ubuntu-focal-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-ubuntu-focal-system-skel" ]; then
#		${MKDIR_CMD} -p ${sharedir}/${platform}-jail-ubuntu-focal-system-skel > /dev/null 2>&1
#		/bin/cp -a ${distdir}/share/${platform}-jail-ubuntu-focal-system-skel/* ${sharedir}/${platform}-jail-ubuntu-focal-system-skel/
#	fi
#	if [ ! -f "${sharedir}/${platform}-jail-debian-buster-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-debian-buster-system-skel" ]; then
#		${MKDIR_CMD} -p ${sharedir}/${platform}-jail-debian-buster-system-skel > /dev/null 2>&1
#		/bin/cp -a ${distdir}/share/${platform}-jail-debian-buster-system-skel/* ${sharedir}/${platform}-jail-debian-buster-system-skel/
#	fi
#	if [ ! -f "${sharedir}/${platform}-jail-debian-bullseye-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-debian-bullseye-system-skel" ]; then
#		${MKDIR_CMD} -p ${sharedir}/${platform}-jail-debian-bullseye-system-skel > /dev/null 2>&1
#		/bin/cp -a ${distdir}/share/${platform}-jail-debian-bullseye-system-skel/* ${sharedir}/${platform}-jail-debian-bullseye-system-skel/
#	fi
#	if [ ! -f "${sharedir}/${platform}-jail-centos-7-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-centos-7-system-skel" ]; then
#		${MKDIR_CMD} -p ${sharedir}/${platform}-jail-centos-7-system-skel > /dev/null 2>&1
#		/bin/cp -a ${distdir}/share/${platform}-jail-centos-7-system-skel/* ${sharedir}/${platform}-jail-centos-7-system-skel/
#	fi
#
#	[ ! -d "${sharedir}/${platform}-jail-kfreebsd-wheezy-skel" -a -d "${platform}/share/${platform}-jail-kfreebsd-wheezy-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-kfreebsd-wheezy-skel ${sharedir}/
#	[ ! -d "${sharedir}/${platform}-jail-ubuntu-focal-skel" -a ! -d "${platform}/share/${platform}-jail-ubuntu-focal-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-ubuntu-focal-skel ${sharedir}/
#	[ ! -d "${sharedir}/${platform}-jail-debian-buster-skel" -a ! -d "${platform}/share/${platform}-jail-debian-buster-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-debian-buster-skel ${sharedir}/
#	[ ! -d "${sharedir}/${platform}-jail-debian-bullseye-skel" -a ! -d "${platform}/share/${platform}-jail-debian-bullseye-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-debian-bullseye-skel ${sharedir}/
#	[ ! -d "${sharedir}/${platform}-jail-centos-7-skel" -a ! -d "${platform}/share/${platform}-jail-centos-7-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-centos-7-skel ${sharedir}/
	[ ! -d "${sharedir}/bhyve-system-default" -a -d "${distdir}/share/bhyve-system-default" ] && /bin/cp -a ${distdir}/share/bhyve-system-default ${sharedir}/
	# legacy
	[ ! -d "${sharedir}/jail-system-default" -a -d "${distdir}/share/jail-system-default" ] && /bin/cp -a ${distdir}/share/jail-system-default ${sharedir}/

	[ ! -d "${sharedir}/FreeBSD-jail-default-system-skel" -a -d "${distdir}/share/FreeBSD-jail-default-system-skel" ] && /bin/cp -a ${distdir}/share/FreeBSD-jail-default-system-skel ${sharedir}/
	[ ! -d "${sharedir}/${platform}-jail-puppet-system-skel" -a -d "${distdir}/share/${platform}-jail-puppet-system-skel" ] && /bin/cp -a ${distdir}/share/${platform}-jail-puppet-system-skel ${sharedir}/
	[ ! -d "${sharedir}/qemu-system-default" -a -d "${distdir}/share/qemu-system-default" ] && /bin/cp -a ${distdir}/share/qemu-system-default ${sharedir}/
	[ ! -d "${sharedir}/xen-system-default" -a -d "${distdir}/share/xen-system-default" ] && /bin/cp -a ${distdir}/share/xen-system-default ${sharedir}/

	[ ! -d "${sharedir}/emulators" -a -d "${distdir}/share/emulators" ] && ${MKDIR_CMD} -p ${sharedir}/emulators
	/bin/cp -a ${distdir}/share/emulators/* ${sharedir}/emulators/
}

phase3()
{
	local _hname _sname _namenotset
	local p

	${ECHO} "${N1_COLOR}[Stage 3: ${N2_COLOR}local settings${N1_COLOR}]${N0_COLOR}"
	_namenotset=1

	while [ ${_namenotset} ]; do
		_hname=$( ${HOSTNAME_CMD} )

		if [ -n "${_hname}" ]; then
			_namenotset=0
			break
		fi

		${ECHO} "${N1_COLOR}Hostname is empty. Please set this:${N0_COLOR}"
		if [ "${inter}" = "0" ]; then
			p="cbsdnode.my.domain"
		else
			read p
		fi
		[ -z "${p}" ] && continue
		${HOSTNAME_CMD} ${p}

		case "${platform}" in
			Linux)
				q="Shall i modify the /etc/hostname to set new hostname value?: ${p}"
				;;
			*)
				q="Shall i modify the /etc/rc.conf to set new hostname value?: ${p}"
				;;
		esac

		if getyesno "${q}" ${initenv_modify_rcconf_hostname}; then
			initenv_modify_rcconf_hostname=1
			case "${platforn}" in
				Linux)
					echo "${p}" > /etc/hostname
					;;
				*)
					/usr/local/cbsd/misc/cbsdsysrc -vf /etc/rc.conf hostname="${p}"
					;;
			esac
		else
			initenv_modify_rcconf_hostname=0
			break
		fi
	done
}

phase4()
{
	${ECHO} "${N1_COLOR}[Stage 4: ${N2_COLOR}update default skel resolv.conf${N1_COLOR}]${N0_COLOR}"

	for i in $(${ECHO} ${jnameserver} | ${TR_CMD} "," " "); do
		if [ -f "${sharedir}/${platform}-jail-skel/etc/resolv.conf" ]; then
			if [ $( ${GREP_CMD} -c ${i} ${sharedir}/${platform}-jail-skel/etc/resolv.conf ) = 0 ]; then
				TMPR="${ftmpdir}/resolv.$$"
				# system nserver must be always last
				${ECHO} "nameserver ${i}" > ${TMPR}
				${CAT_CMD} ${sharedir}/${platform}-jail-skel/etc/resolv.conf >> ${TMPR}
				${MV_CMD} ${TMPR} ${sharedir}/${platform}-jail-skel/etc/resolv.conf
			fi
		fi
	done
}

phase5()
{
	local _uncfg _uninit _checkme _myfs _ret _val _tmpval

	${ECHO} "${N1_COLOR}[Stage 5: ${N2_COLOR}refreshing inventory${N1_COLOR}]${N0_COLOR}"

	[ -f "${inventory}" ] && . ${inventory}

	# adjust some defaults
	[ -z "${nodeip}" ] && nodeip="auto"
	[ -z "${nodeip6}" ] && nodeip6="auto"
	[ -z "${natip}" ] && natip="auto"
	[ -z "${natip6}" ] && natip6="auto"
	[ -z "${nodeippool}" ] && nodeippool="auto"
	#system information
	. ${toolsdir}/sysinv
	update_netinfo
	init_items_desc
	init_items_default

	if [ -z "${nodename}" ]; then
		desc_question nodename
		nodename=${answ}
	fi

	[ "${nodename}" = "auto" ] && nodename=$( ${HOSTNAME_CMD} )
	[ -z "${nodename}" ] && err 1 "nodename must be not empty"

	if [ "${nodeip}" = "auto" ]; then
		case "${node_ip4_active}" in
			1)
				if [ "${CBSD_IP4}" = "127.0.0.1" ]; then
					nodeip="0"	# disabled
				else
					nodeip="${CBSD_IP4}"
				fi
				;;
			*)
				nodeip="0"		# disabled
				;;
		esac
	fi

	if [ "${nodeip6}" = "auto" ]; then
		case "${node_ip6_active}" in
			1)
				if [ "${CBSD_IP6}" = "::1" ]; then
					nodeip6="0"	# disabled
				else
					nodeip6="${CBSD_IP6}"
				fi
				;;
			*)
				nodeip6="0"		# disabled
				;;
		esac
	fi

	[ "${natip}" = "auto" ] && natip="${CBSD_IP4}"
	[ "${natip6}" = "auto" ] && natip6="${CBSD_IP6}"

#	debug
#	echo "STATE ${nodename}"
#	echo "nodeip: ${nodeip}"
#	echo "nodeip6: ${nodeip6}"
#	echo "natip: ${natip}"
#	echo "natip6: ${natip6}"
#	echo "node_ip4_active: ${node_ip4_active}"
#	echo "node_ip6_active: ${node_ip6_active}"
#	exit 0

	[ ! -f "${nodenamefile}" ] && echo "${nodename}" > "${nodenamefile}"
	[ ! -f "${dbdir}/nodes.sqlite" ] && env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/nodes.sqlite ${distdir}/share/node-nodelist.schema nodelist

	if [ ! -f "${dbdir}/inv.${nodename}.sqlite" ]; then
		env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-unconfigured.schema unconfigured
		env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-local.schema local
		env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-jails.schema jails
		$ECHO "${N1_COLOR}Empty inventory database created: ${N2_COLOR}${dbdir}/inv.${nodename}.sqlite${N0_COLOR}"
		${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite "INSERT INTO local ( nodename ) VALUES ( '${nodename}' )"
	fi

	# extra re-check for empty values
	_tmp_nodename=$( ${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite "SELECT nodename FROM local" 2>/dev/null )
	[ -z "${_tmp_nodename}" ] && ${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite "INSERT INTO local ( nodename ) VALUES ( '${nodename}' )"
	_tmp_nodename=$( ${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite "SELECT nodename FROM local" 2>/dev/null )
	if [ -z "${_tmp_nodename}" ]; then
		echo "error query: ${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite \"INSERT INTO local ( nodename ) VALUES ( '${nodename}' )\""
		exit 1
	fi

	${CHMOD_CMD} 0660 ${dbdir}/inv.${nodename}.sqlite && ${CHOWN_CMD} ${cbsduser}:${cbsduser} ${dbdir}/inv.${nodename}.sqlite

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-local.schema local
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-carp.schema carp

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-bsdbase.schema bsdbase
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-bsdkernel.schema bsdkernel

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-bsdsrc.schema bsdsrc
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vale.schema vale
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vale_ports.schema vale_ports

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/forms.schema forms
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/forms_system.schema system

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-jails.schema jails
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-rctl.schema rctl

	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-bhyve.schema bhyve
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-bhyveppt.schema bhyveppt
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-virtualbox.schema virtualbox
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-xen.schema xen
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-qemu.schema qemu
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vnetnic.schema vnetnic
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vmpackages.schema vmpackages

	# insert sample/defaults
	_tmpval=$( ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT name FROM vmpackages WHERE name='small1' LIMIT 1" )
	if [ -z "${_tmpval}" ]; then
		${miscdir}/sqlcli ${dbdir}/local.sqlite "INSERT INTO vmpackages ( name, pkg_vm_cpus, pkg_vm_ram, pkg_vm_disk, owner ) VALUES ( 'small1',  '1', '2g',  '20g',  'admin' )"
		${miscdir}/sqlcli ${dbdir}/local.sqlite "INSERT INTO vmpackages ( name, pkg_vm_cpus, pkg_vm_ram, pkg_vm_disk, owner ) VALUES ( 'medium1', '4', '8g',  '60g',  'admin' )"
		${miscdir}/sqlcli ${dbdir}/local.sqlite "INSERT INTO vmpackages ( name, pkg_vm_cpus, pkg_vm_ram, pkg_vm_disk, owner ) VALUES ( 'large1',  '8', '16g', '100g', 'admin' )"
	fi
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vm_cpu_topology.schema vm_cpu_topology
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/cbsdtaskd.sqlite ${distdir}/share/cbsdtaskd-taskd.schema taskd
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/vpnet.sqlite ${distdir}/share/vpnet-vpnet.schema vpnet
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/authkey.sqlite ${distdir}/share/local-authkey.schema authkey
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/storage_media.sqlite ${distdir}/share/local-storage_media_map.schema media
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/images.sqlite ${distdir}/share/local-images.schema images
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-storage_pools.schema storage_pools

	_tmpval=$( ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT id FROM storage_pools LIMIT 1" )
	if [ -z "${_tmpval}" ]; then
		${miscdir}/sqlcli ${dbdir}/inv.${nodename}.sqlite "INSERT INTO storage_pools (id,name,driver,description,poolpath,state) VALUES(1,'default','dir','','jails-data',1); )"
	fi

	[ -f "${dbdir}/nodes.sqlite" ] && env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/nodes.sqlite ${distdir}/share/node-nodelist.schema nodelist

	cd ${dbdir}
	#${LN_CMD} -sfh inv.${nodename}.sqlite local.sqlite
	${LN_CMD} -sfn inv.${nodename}.sqlite local.sqlite

	_myfs="ufs"

	init_zfs_feat

	case ${zfsfeat} in
		1)
			_myfs="zfs"
			;;
		*)
			true
			;;
	esac

	${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET zfsfeat='${zfsfeat}'"

	if [ -x /sbin/hammer2 ]; then
		/sbin/hammer2 info ${workdir} > /dev/null 2>&1
		[ $? -eq 0 ] && _myfs="hammer"
	fi

	_uncfg=$( ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT items FROM unconfigured" )
	[ $? -ne 0 ] && err 1 "Error for unconfigured query"

	if [ -n "${INITCFG}" ]; then
		onodename="${nodename}"
		. ${INITCFG}
		[ -n "${CBSD_INITCFG_EXTRA}" ] && . ${CBSD_INITCFG_EXTRA}
		_uncfg=$( ${GREP_CMD} -v '^#' ${INITCFG} | ${CUT_CMD} -d '=' -f1 | ${XARGS_CMD} )
		nodename="${onodename}"
	fi

	if [ "${nodeippool}" = "auto" ]; then
		_tmpval=$( /usr/local/bin/cbsd find_free_cidr4 )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			nodeippool="10.0.0.1/24"
		else
			nodeippool="${_tmpval}"
		fi

		export nodeippool="${nodeippool}"
		export nodeippool_default="${nodeippool}"
		#${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET nodeippool='${nodeippool}'"
	fi

	for _checkme in ${_uncfg}; do
		for _uninit in ${USERINI}; do
			# skip for nodename which is already set
			[ "${_uninit}" = "nodename" ] && continue
			# temporary skip for mdtmp
			[ "${_uninit}" = "mdtmp" ] && continue
			if [ "${_uninit}" = "${_checkme}" ]; then
				if [ "${_checkme}" = "zfsfeat" -a ${_myfs} != "zfs" ]; then
					${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET zfsfeat='0'"
					continue
				fi
				if [ "${_checkme}" = "hammerfeat" -a ${_myfs} != "hammer" ]; then
					${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET hammer='0'"
					continue
				fi

				# check for pre-defined variables
				T=
				eval T="\$$_checkme"
				[ -n "${T}" ] && export ${_checkme}_default="${T}"

				desc_question ${_checkme}
				[ $? -ne 0 ] && continue
				# todo: input validation here
				[ "${_checkme}" = "mdtmp" -a "$answ" = "1" ] && answ="8"
				[ "${_checkme}" = "mdtmp" -a "$answ" = "2" ] && answ="0"
				if [ -n "${answ}" ]; then
					${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET ${_uninit}='${answ}'"
					eval "${_uninit}=\"${answ}\"" 2>/dev/null
				fi
				if [ "${_checkme}" = "nat_enable" -a  "${nat_enable}" != "0" ]; then
					# store in nat_enable default NAT framework, e.g: pf
					case "${platform}" in
						Linux)
							nat_enable="nft"
							;;
						*)
							nat_enable="pf"
							;;
					esac
					configure_nat
				fi

				if [ -n "${INITCFG_PRESEED}" ]; then
					/usr/local/cbsd/misc/cbsdsysrc -qf ${INITCFG_PRESEED} ${_checkme}="${answ}" > /dev/null
				fi
			fi
		done
	done

	# flush unconfigured marker
	${miscdir}/sqlcli ${dbdir}/local.sqlite "DELETE FROM unconfigured"
	# constants and static param. FIX ME
	${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET repo='https://convectix.com'"
	${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET workdir='${workdir}'"

	oipfw_enable="${ipfw_enable}"

	_ret=$( ${SYSCTL_CMD} -n net.inet.ip.fw.enable 2>/dev/null )
	if [ "${_ret}" = "1" ]; then
		_ret=1
	else
		_ret=0
	fi

	# Overwrite $platform to HardenedBSD if we have /usr/sbin/hbsd-update:
	[ -e "/usr/sbin/hbsd-update" ] && platform="HardenedBSD"

	if [ -z "${oipfw_enable}" ]; then
		ipfw_enable="${_ret}"
	else
		ipfw_enable="${oipfw_enable}"
	fi

	fs="${_myfs}"

	for i in ipfw_enable fs jail_interface nodedescr nodename hostname racct platform node_ip4_active node_ip6_active nodeip natip; do
		T=
		eval T="\$$i"
		[ -z "${T}" ] && T="0"
		${miscdir}/sqlcli ${dbdir}/local.sqlite "UPDATE local SET ${i}='${T}'"
	done

	if [ -n "${INITCFG_PRESEED}" -a -r "${INITCFG_PRESEED}" ]; then
		for i in ipfw_enable nodename racct nodeip natip; do
			T=
			eval T="\$$i"
			/usr/local/cbsd/misc/cbsdsysrc -qf ${INITCFG_PRESEED} ${i}="${T}" >/dev/null
		done
	fi

	local FILES="descr role domain notes location"
	for i in $FILES; do
		[ ! -f "${workdir}/${i}" ] && ${TOUCH_CMD} ${workdir}/node.${i} && ${CHOWN_CMD} cbsd:cbsd ${workdir}/node.${i}
	done

	env workdir=${workdir} /usr/local/bin/cbsd netinv
	# temporary update ascii inventory
	env sqlcolnames="1" ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT * FROM local" > ${inventory}
	local _formfile="${jailsysdir}/CBSDSYS/helpers/cbsd.sqlite"

	[ ! -r  ${_formfile} ] && return 0

	for i in cbsdd_enable nodename nodeip jnameserver nodeippool ipfw_enable parallel stable sqlreplica; do
		myval=
		eval myval=\$${i}
		tmpval=$( /usr/local/bin/sqlite3 ${_formfile} "SELECT cur FROM forms WHERE param='${i}' LIMIT 1" )
		if [ -z "${tmpval}" ]; then
			/usr/local/bin/sqlite3 ${_formfile} "UPDATE forms SET cur='${myval}' WHERE param='${i}'"
		fi
	done
}

phase6()
{
	${ECHO} "${N1_COLOR}[Stage 6: ${N2_COLOR}authentication keys${N1_COLOR}]${N0_COLOR}"

	install_sshkey
}

phase7()
{
	local SECCMD _i _cmd _lnk _dst _modulename _moduledir
	${ECHO} "${N1_COLOR}[Stage 7: ${N2_COLOR}nodes${N1_COLOR}]${N0_COLOR}"

	# create hook.d dir for nodes
	for _i in ${nodedir} ${nodedir}/add.d ${nodedir}/remove.d ${nodedir}/offline.d ${nodedir}/online.d; do
		if [ ! -d "${_i}" ]; then
			${MKDIR_CMD} -p -m 0775 ${_i}
			${CHOWN_CMD} root:cbsd ${nodedir}
		fi
	done

	[ ! -f "${etcdir}/nodes.conf" ] && return 0
}

phase8()
{
	local SECCMD _i _cmd _lnk _dst _modulename _moduledir
	${ECHO} "${N1_COLOR}[Stage 8: ${N2_COLOR}modules${N1_COLOR}]${N0_COLOR}"

	# buildah module
	[ -n "${BUILDAH_CMD}" ] && /usr/local/bin/cbsd buildah

	if [ ! -d "${moduledir}" ]; then
		${MKDIR_CMD} -p -m 0775 ${moduledir}
		${CHOWN_CMD} root:cbsd ${moduledir}
	fi

	[ ! -f "${etcdir}/modules.conf" ] && return 0
	# Deinstall module first
	for _lnk in $( ${FIND_CMD} ${moduledir} -mindepth 1 -maxdepth 1 -type l ); do
		_dst=$( ${READLINK_CMD} ${_lnk} )
		_dst=$( ${DIRNAME_CMD} ${_dst} )
		#append slash for next excluding in _modulename
		_moduledir="${distmoduledir}/"
		_modulename="${_dst#$_moduledir}"
		_my_module=$( echo ${_modulename} | ${SED_CMD} 's:\.d$::g' )	# strip .d$

		${GREP_CMD} "^${_modulename}" ${etcdir}/modules.conf >/dev/null 2>&1
		if [ $? -eq 1 ]; then
			${ECHO} "${N1_COLOR}Removing module ${_modulename} cmd: ${N2_COLOR}${_dst}${N0_COLOR}"
			${RM_CMD} -f ${_lnk}
			/usr/local/cbsd/misc/cbsdsysrc -qf ${inventory} mod_${_my_module}_enabled="NO" > /dev/null 2>&1
		fi
	done

	# Install module
	for _i in $( ${CAT_CMD} ${etcdir}/modules.conf ); do
		[ ! -f "${distmoduledir}/${_i}/securecmd" ] && continue
		. ${distmoduledir}/${_i}/securecmd
		_my_module=$( echo ${_i} | ${SED_CMD} 's:\.d$::g' )	# strip .d$
		for _cmd in ${SECCMD}; do
			if [ ! -h "${moduledir}/${_cmd}" ]; then
				#${LN_CMD} -sfh ${distmoduledir}/${_i}/${_cmd} ${moduledir}/${_cmd}
				${LN_CMD} -sfn ${distmoduledir}/${_i}/${_cmd} ${moduledir}/${_cmd}
				${ECHO} "${N1_COLOR}Installing module ${_i} cmd: ${N2_COLOR}${_cmd}${N0_COLOR}"
			fi
		done

		_my_module=$( echo ${_my_module} | ${TR_CMD} "-" "_" )	# cast '-' to '_'
		/usr/local/cbsd/misc/cbsdsysrc -qf ${inventory} mod_${_my_module}_enabled="YES" > /dev/null 2>&1
	done
}

phase9()
{
	local OLD_FILES OLD_DIRS
	. ${distdir}/ObsoleteFiles

	# append for modules Obsolete cmd part
	if [ -f "${etcdir}/modules.conf" ]; then
		for i in $( ${CAT_CMD} ${etcdir}/modules.conf ); do
			[ ! -f "${moduledir}/${i}/ObsoleteFiles" ] && continue
			. ${moduledir}/${i}/ObsoleteFiles
		done
	fi

	${ECHO} "${N1_COLOR}[Stage 9: ${N2_COLOR}cleanup${N1_COLOR}]${N0_COLOR}"
	$ECHO "${N1_COLOR} * Remove obsolete files..."

	for i in $OLD_FILES; do
		[ -f "${workdir}/${i}" -o -h "${workdir}/${i}" ] && ${ECHO} "    ${N1_COLOR}Removing obsolete file: ${N2_COLOR}${workdir}/${i}${N0_COLOR}" && ${RM_CMD} -f ${workdir}/${i}
	done

	for i in $OLD_DIRS; do
		[ -d "${workdir}/${i}" -o -h "${workdir}/${i}" ] && ${ECHO} "    ${N1_COLOR}Removing obsolete dir: ${N2_COLOR}${workdir}/${i}${N0_COLOR}" && ${RMDIR_CMD} ${workdir}/${i}
	done
	printf "${N0_COLOR}"
}

post_message()
{
	[ ${first_init} -eq 0 ] && return 0
	unset NOCOLOR
	. ${subrdir}/ansiicolor.subr
	case "${platform}" in
		Linux)
			ECHO=$( ${WHICH_CMD} echo )
			ECHO="${ECHO} -e"
			;;
		*)
			ECHO="echo -e"
			;;
	esac
	${ECHO} "  ${N2_COLOR}${UNDERLINE}Congratulations! First CBSD initialization complete!${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}Now your can run:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}service cbsdd start${N0_COLOR}${N2_COLOR}"
	${ECHO} "  ${N2_COLOR}to run CBSD services.${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}For change initenv settings in next time, use:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd initenv-tui${N0_COLOR}${N2_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}Also don't forget to execute:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd initenv${N0_COLOR}${N2_COLOR}"
	${ECHO} "  ${N2_COLOR}every time when you upgrade CBSD version.${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}For an easy start:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd help"
	${ECHO}
	${ECHO} "  ${N2_COLOR}General information:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd summary"
	${ECHO}
	${ECHO} "  ${N2_COLOR}To start with jail:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd jcreate --help${N0_COLOR}"
	${ECHO} "  ${N2_COLOR}or: ${N0_COLOR}${BOLD}cbsd jconstruct-tui${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}To start with bhyve:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd bcreate --help${N0_COLOR}"
	${ECHO} "  ${N2_COLOR}or: ${N0_COLOR}${BOLD}cbsd bconstruct-tui${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}To start with XEN:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd xcreate --help${N0_COLOR}"
	${ECHO} "  ${N2_COLOR}or: ${N0_COLOR}${BOLD}cbsd xconstruct-tui${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${N2_COLOR}To start with QEMU/NVMM:${N0_COLOR}"
	${ECHO} "  ${N0_COLOR}${BOLD}cbsd qcreate --help${N0_COLOR}"
	${ECHO} "  ${N2_COLOR}or: ${N0_COLOR}${BOLD}cbsd qconstruct-tui${N0_COLOR}"
	${ECHO}
	${ECHO} "  ${H3_COLOR}Enjoy CBSD!${N0_COLOR}"
	${ECHO}
}

############ start locking section #############
start()
{
	if [ -n "${CBSD_INITCFG_EXTRA}" -a -r "${CBSD_INITCFG_EXTRA}" ]; then
		trap "${RM_CMD} -f ${CBSD_INITCFG_EXTRA}" HUP INT ABRT BUS TERM EXIT
	fi

	if [ -n "${INITCFG}" ]; then
		inter=0
		ALWAYS_YES=1
		. "${INITCFG}" 2>/dev/null
		[ -n "${CBSD_INITCFG_EXTRA}" ] && . ${CBSD_INITCFG_EXTRA}
	fi

	[ -z "${ECHO}" ] && ECHO="echo -e"

	if [ -z "${workdir}" ]; then
		if [ -n "${cbsd_workdir}" ]; then
			export workdir="${cbsd_workdir}"
		else
			. /etc/rc.conf
			if [ -n "${cbsd_workdir}" ]; then
				export workdir="${cbsd_workdir}"
			else
				export workdir="/usr/jails"
			fi
		fi
	fi

	. ${globalconf}
	. ${subrdir}/nc.subr
	. ${subrdir}/tools.subr
	. ${subrdir}/initenv.subr
	. ${subrdir}/ansiicolor.subr

	if [ "${workdir}" = "${distdir}" ]; then
		${ECHO} "${N1_COLOR}Please use difference path for workdir. Not ${N2_COLOR}${distdir}${N0_COLOR}"
		exit 1
	fi

	[ ! -d "${TMPDIR}" ] && TMPDIR="/tmp"

	${CAT_CMD} << EOF_HEADER
-------[${product} v.${myversion}]-------
 This is install/upgrade scripts for ${product}.
 Don't forget to backup.
-----------------------------
EOF_HEADER

	if [ "${inter}" != "0" ]; then
		getyesno "Do you want prepare or upgrade hier environment for ${product} now?" || exit 0
	fi

	${ECHO} "${N1_COLOR}>>> Installing or upgrading${N0_COLOR}"
	phase0
	phase0X			# pre-migrate script
	phase1
	phase2
	phase3

	[ -z "${cbsd_workdir}" -a -r /etc/rc.conf ] && . /etc/rc.conf
	[ -z "${cbsd_workdir}" ] && cbsd_workdir="${workdir}"
	[ -z "${cbsd_workdir}" ] && err 1 "no such cbsd_workdir vars"
	[ ! -r ${workdir}/rc.conf ] && ${TOUCH_CMD} ${workdir}/rc.conf

	if [ "${cbsd_workdir}" != "${workdir}" ]; then
		if [ $( ${GREP_CMD} ^cbsd_workdir= /etc/rc.conf ${workdir}/rc.conf | ${WC_CMD} -l ) = 0 ]; then
			if getyesno "Shall i modify the /etc/rc.conf to sets cbsd_workdir=\"${workdir}\"?: ${p}" ${initenv_modify_rcconf_cbsd_workdir}; then
				initenv_modify_rcconf_cbsd_workdir=1
				/usr/local/cbsd/misc/cbsdsysrc -vf /etc/rc.conf cbsd_workdir="${workdir}"
			else
				initenv_modify_rcconf_cbsd_workdir=0
				/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf cbsd_workdir="${workdir}"
			fi
		fi
	fi

	if [ $( ${GREP_CMD} ^cbsd_workdir= /etc/rc.conf ${workdir}/rc.conf | ${WC_CMD} -l ) = 0 ]; then
		if getyesno "Shall i modify the /etc/rc.conf to sets cbsd_workdir=\"${workdir}\"?: ${p}" ${initenv_modify_rcconf_cbsd_workdir}; then
			initenv_modify_rcconf_cbsd_workdir=1
			/usr/local/cbsd/misc/cbsdsysrc -vf /etc/rc.conf cbsd_workdir="${workdir}"
		else
			initenv_modify_rcconf_cbsd_workdir=0
			/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf cbsd_workdir="${workdir}"
		fi
	fi

	if [ ${first_init} -eq 1 ]; then
		if [ $( ${GREP_CMD} ^preseedinit= ${workdir}/rc.conf | ${WC_CMD} -l ) = 0 ]; then
			if [ ${inter} -eq 1 ]; then
				INITCFG_PRESEED=$( mktemp )
				${CAT_CMD} > ${INITCFG_PRESEED} <<EOF
# cbsd initenv preseed file for $( hostname ) host
# refer to the /usr/local/cbsd/share/initenv.conf
# for description.
#
EOF
			fi
		fi
	fi

	phase4
	phase5
	# Inventory area
	phase6

	#Finnaly export new inventory from SQLite data for ASCii
	collect_info
	update_hwinfo
	env sqlcolnames="1" ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT * FROM local" > ${inventory}
	${CHMOD_CMD} 0640 ${inventory} && ${CHOWN_CMD} ${cbsduser}:${cbsduser} ${inventory}
	# end of Inventory
	phase7
	phase8
	phase9

	[ ! -f "${workdir}/rc.conf" ] && ${TOUCH_CMD} ${workdir}/rc.conf
	configure_rsync
	configure_racct

	SYSTEMCTL_CMD=$( ${WHICH_CMD} systemctl )

	if [ $( ${GREP_CMD} ^cbsdd_enable= /etc/rc.conf ${workdir}/rc.conf 2>/dev/null | ${WC_CMD} -l ) = 0 ]; then
		case "${platform}" in
			Linux)
				q="Do you want to activate cbsdd service at system startup?"
				;;
			*)
				q="Shall i modify the /etc/rc.conf to sets cbsdd_enable=YES ?"
				;;
		esac
		if getyesno "${q}" ${initenv_modify_rcconf_cbsd_enable}; then
			initenv_modify_rcconf_cbsd_enable=1
		else
			initenv_modify_rcconf_cbsd_enable=0
		fi

		case ${initenv_modify_rcconf_cbsd_enable} in
			1)
				case "${platform}" in
					Linux)
						if [ -z "${SYSTEMCTL_CMD}" ]; then
							echo "no systemctl, skip"
							break
						fi
						if [ ! -d "/lib/systemd/system" ]; then
							echo "no /lib/systemd/system, skip"
							break
						fi
						[ ! -r /lib/systemd/system/cbsdd.service ] && ${SED_CMD} s:%%CBSD_WORKDIR%%:${cbsd_workdir}:g ${distdir}/share/examples/systemd/cbsdd.service > /lib/systemd/system/cbsdd.service
						${SYSTEMCTL_CMD} enable cbsdd.service
						;;
					*)
						true
						;;
				esac
				/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf cbsdd_enable=YES
				/usr/local/cbsd/misc/cbsdsysrc -qf /etc/rc.conf cbsdd_enable="YES"
				;;
			*)
				/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf cbsdd_enable="NO"
				/usr/local/cbsd/misc/cbsdsysrc -qf /etc/rc.conf cbsdd_enable="NO"
				;;
		esac
	else
		if [ "${platform}" = "Linux" ]; then
			if [ -z "${SYSTEMCTL_CMD}" ]; then
					echo "no systemctl, skip"
					break
			else
				[ ! -r /lib/systemd/system/cbsdd.service ] && ${SED_CMD} s:%%CBSD_WORKDIR%%:${cbsd_workdir}:g ${distdir}/share/examples/systemd/cbsdd.service > /lib/systemd/system/cbsdd.service
				if [ -n "${cbsdd_enable}" ]; then
					if [ "${cbsdd_enable}" = "YES" ]; then
						_cbsd_enable=1
					else
						_cbsd_enable=1
					fi
				else
					_cbsd_enable="${initenv_modify_rcconf_cbsd_enable}"
				fi
				case ${_cbsd_enable} in
					1)
						${SYSTEMCTL_CMD} enable cbsdd.service
						;;
					*)
						${SYSTEMCTL_CMD} disable cbsdd.service
						;;
				esac
			fi
		fi
	fi

	[ -z "${rcshutdown_timeout}" ] && rcshutdown_timeout="0"

	if [ $( ${GREP_CMD} ^rcshutdown_timeout= /etc/rc.conf ${workdir}/rc.conf | ${WC_CMD} -l ) = 0 ]; then
		if getyesno "Shall i modify the /etc/rc.conf to sets rcshutdown_timeout=\"900\"?" ${initenv_modify_rcconf_rcshutdown_timeout}; then
			initenv_modify_rcconf_rcshutdown_timeout=1
			/usr/local/cbsd/misc/cbsdsysrc -vf /etc/rc.conf rcshutdown_timeout="900"
			rcshutdown_timeout="900"
		else
			initenv_modify_rcconf_rcshutdown_timeout=0
			/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf rcshutdown_timeout="900"
		fi
	fi

	kern_init_shutdown_timeout=$( ${SYSCTL_CMD} -qn kern.init_shutdown_timeout 2>/dev/null )
	[ -z "${kern_init_shutdown_timeout}" ] && kern_init_shutdown_timeout="${rcshutdown_timeout}"	# unknown sysctl ? skip

	if [ ${kern_init_shutdown_timeout} -lt ${rcshutdown_timeout} ]; then
		if [ $( ${GREP_CMD} -E "^kern.init_shutdown_timeout=|^kern_init_shutdown_timeout=" /etc/sysctl.conf ${workdir}/rc.conf | ${WC_CMD} -l ) = 0 ]; then
			if getyesno "Shall i modify the /etc/sysctl.conf to sets kern.init_shutdown_timeout=\"900\"?" ${initenv_modify_syctl_rcshutdown_timeout}; then
				initenv_modify_syctl_rcshutdown_timeout=1
				printf "\nkern.init_shutdown_timeout=\"900\"\n" >> /etc/sysctl.conf
				kern_init_shutdown_timeout="900"
				${SYSCTL_CMD} -qw kern.init_shutdown_timeout="900"
			else
				initenv_modify_syctl_rcshutdown_timeout=0
				/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf kern_init_shutdown_timeout="900"
			fi
		fi
	fi

	# show warning if ${rcshutdown_timeout} has no effect due to wrong ${kern_init_shutdown_timeout} value
	if [ ${kern_init_shutdown_timeout} -lt ${rcshutdown_timeout} ]; then
		${ECHO} "${W1_COLOR}Warning: ${N1_COLOR}kern.init_shutdown_timeout(${kern_init_shutdown_timeout}) less than rcshutdown_timeout(${rcshutdown_timeout})${N0_COLOR}"
		${ECHO} "${N1_COLOR}Current setting of rcshutdown_timeout will have no effect until the sysctl(8) variable kern.init_shutdown_timeout is also increased${N1_COLOR}"
	fi

	phaseX

	hash -r
	${ECHO} "${N1_COLOR}>>> Done${N0_COLOR}"
	post_message

	if [ -n "${INITCFG_PRESEED}" -a -r "${INITCFG_PRESEED}" ]; then

		for i in initenv_modify_sudoers \
			initenv_modify_rcconf_hostname \
			initenv_modify_rcconf_cbsd_workdir \
			initenv_modify_rcconf_cbsd_enable \
			initenv_modify_rcconf_rcshutdown_timeout \
			initenv_modify_syctl_rcshutdown_timeout \
			initenv_modify_rcconf_cbsdrsyncd_enable \
			initenv_modify_rcconf_cbsdrsyncd_flags \
			initenv_modify_cbsd_homedir \
			workdir; do
			T=
			eval T="\$$i"
			/usr/local/cbsd/misc/cbsdsysrc -qf ${INITCFG_PRESEED} ${i}="${T}" >/dev/null
		done

		preseedinit_desc="Would you like a config for \"cbsd init\" preseed to be printed?"
		preseedinit_default="0"

		desc_question "preseedinit"
		if [ $? -eq 0 -a "${answ}" = "1" ]; then
			${CP_CMD} ${INITCFG_PRESEED} /tmp/prs.txt

			echo
			echo "---cut here ---"
			${CAT_CMD}  ${INITCFG_PRESEED}
			echo "---end of cut---"
			echo

		fi
		${RM_CMD} -f ${INITCFG_PRESEED}

		/usr/local/cbsd/misc/cbsdsysrc -qf ${workdir}/rc.conf preseedinit="${answ}" > /dev/null 2>&1
	fi

	if [ ${first_init} -eq 1 ]; then
		[ -r /etc/rc.conf ] && . /etc/rc.conf
		if [ "${cbsdd_enable}" = "YES" ]; then
			printf "Starting service: cbsdd ... "
			case "${platform}" in
				Linux)
					[ -z "${SYSTEMCTL_CMD}" ] && echo "no systemctl cmd" && break
					${SYSTEMCTL_CMD} stop cbsdd.service > /dev/null 2>&1 || true
					${SYSTEMCTL_CMD} start cbsdd.service > /dev/null 2>&1
					_ret=$?
					;;
				*)
					[ -z "${SERVICE_CMD}" ] && echo "no service cmd" && break
					${SERVICE_CMD} cbsdd stop > /dev/null 2>&1 || true
					${SERVICE_CMD} cbsdd start > /dev/null 2>&1
					_ret=$?
					;;
			esac
			case "${_ret}" in
				0)
					${ECHO} "${N2_COLOR}done${N0_COLOR}"
					;;
				1)
					${ECHO} "${W1_COLOR}failed${N0_COLOR}"
					;;
			esac
		fi
	fi

	exit 0
}

# export LOCK_CMD
init_lock()
{
	local _lock_cmd
	LOCK_CMD=

	_lock_cmd=$( ${WHICH_CMD} lockf 2>/dev/null )

	if [ -n "${_lock_cmd}" -a -x "${_lock_cmd}" ]; then
		LOCK_CMD="${_lock_cmd} -t0 -s "
	else
		_lock_cmd=$( ${WHICH_CMD} flock 2>/dev/null )
		if [ -n "${_lock_cmd}" -a -x ${_lock_cmd} ]; then
			LOCK_CMD="${_lock_cmd} -w0 -x "
		fi
	fi

	if [ -z "${LOCK_CMD}" ]; then
		echo "No such lock management stuff (lockf, flock)"
		exit 0
	fi
}

### MAIN ###
WHICH_CMD=$( which which 2>/dev/null )
[ -z "${WHICH_CMD}" ] && err 1 "initenv error: no such executable dependency/requirement: which"

TR_CMD=$( ${WHICH_CMD} tr 2>/dev/null )
[ -z "${TR_CMD}" ] && err 1 "initenv error: no such executable dependency/requirement: tr"

UNAME_CMD=$( ${WHICH_CMD} uname 2>/dev/null )
[ -z "${UNAME_CMD}" ] && err 1 "initenv error: no such executable dependency/requirement: uname"

# 'uname' before macros here
OS=$( ${UNAME_CMD} -s )
platform="${OS}"
arch=$( ${UNAME_CMD} -p )

init_lock

if [ -z "${workdir}" ]; then
	if [ -z "${cbsd_workdir}" ]; then
		if [ -r /etc/rc.conf ]; then
			. /etc/rc.conf
		fi
	fi
	if [ -n "${cbsd_workdir}" ]; then
		workdir="${cbsd_workdir}"
	else
		workdir="/usr/jails"
	fi
fi

# for first boot fallback
export oworkdir="${workdir}"

if [ $# -ne 1 ]; then
	if [ "${inter}" = "0" ]; then
		${LOCK_CMD} ${MYLOCK} env INITCFG="${INITCFG}" CBSD_INITCFG_EXTRA="${CBSD_INITCFG_EXTRA}" $0 inter=0 start
	else
		${LOCK_CMD} ${MYLOCK} env INITCFG="${INITCFG}" CBSD_INITCFG_EXTRA="${CBSD_INITCFG_EXTRA}" $0 start
	fi
fi

[ -n "${INITCFG}" -a -r "${INITCFG}" ] && . ${INITCFG}
[ -n "${CBSD_INITCFG_EXTRA}" ] && . ${CBSD_INITCFG_EXTRA}

set -e
. ${distdir}/cbsd.conf
set +e

# Overwrite $platform to HardenedBSD if we have /usr/sbin/hbsd-update:
[ -e "/usr/sbin/hbsd-update" ] && platform="HardenedBSD"

[ -f "${subrdir}/cmd.subr" ] && . ${subrdir}/cmd.subr

MAIN_EXTRA_CMD=

# generic mandatory tools/script
MAIN_CMD="
awk
date
basename
cat
chown
cmp
cp
cut
chmod
dd
df
dirname
find
grep
head
hostname
install
ln
ls
mkdir
mktemp
mount
realpath
readlink
rm
rmdir
sed
seq
sort
sysctl
tar
tail
touch
truncate
umount
xargs
wc
"

case "${platform}" in
	Linux)
		MAIN_EXTRA_CMD="${MAIN_EXTRA_CMD} usermod"
		true
		;;
	FreeBSD)
		MAIN_EXTRA_CMD="${MAIN_EXTRA_CMD} kldstat pw service"
		;;
esac

for i in ${MAIN_CMD} ${MAIN_EXTRA_CMD}; do
	mycmd=
	mycmd=$( ${WHICH_CMD} ${i} || true )            # true for 'set -e' case
	[ ! -x "${mycmd}" ] && err 1 "${pgm} error: no such executable dependency/requirement: ${i}"
	MY_CMD=$( echo ${i} | ${TR_CMD} '\-[:lower:]' '_[:upper:]' )
	MY_CMD="${MY_CMD}_CMD"
	eval "${MY_CMD}=\"${mycmd}\""
done

[ -f "${subrdir}/${platform}.subr" ] && . ${subrdir}/${platform}.subr

case "$1" in
	start)
		start
	;;
esac

exit 0
