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

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

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
	. ${INITCFG}
fi

# 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=$( /usr/bin/head -c 30 /dev/random | /usr/bin/uuencode -m - | /usr/bin/tail -n 2 | /usr/bin/head -n1 )
			${ECHO} "${N1_COLOR} * write directory id: ${i}${N0_COLOR}"
			echo "${_id}" > ${_dir}/dir.id
		fi
	done
}

desc_question()
{
	local _DEFAULT
	local _DESC

	if [ "${inter}" = "0" ]; then
		eval answ=\$$1
		return 0
	fi

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

	case "$1" in
		"fbsdrepo")
			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
			[ "${answ}" = "default" ] && 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")
			${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")
			${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")
			${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")
			${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")
			${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")
			${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")
			${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
			;;
		*)
			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 workdir

	. ${distdir}/${localcbsdconffile}
	newver="${myversion}"

	# touch must be in paths until phase1 generates <cmd>_CMD macros
	[ ! -f /etc/rc.conf ] && touch /etc/rc.conf
	[ -z "${cbsd_workdir}" ] && . /etc/rc.conf
	[ -z "${cbsd_workdir}" ] && return 0
	[ ! -x ${miscdir}/sqlcli ] && return 0	# no build/first run?

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

	cbsdver=
	oldver=

	workdir="${cbsd_workdir}"
	[ -r "${inventory}" ] && . ${inventory}
	[ -z "${cbsdver}" ] && cbsdver="unknown"
	oldver="${cbsdver}"
}

phase0X()
{
	[ -z "${workdir}" ] && return 0
	[ ! -r "${workdir}/var/db/local.sqlite" ] && return 0
	${ECHO} "${N1_COLOR}[Stage 0:${N2_COLOR} upgrading and migration data from ${oldver} to ${newver}${N1_COLOR}]${N0_COLOR}"
	[ -d "${workdir}/upgrade" ] && env workdir="${workdir}" /usr/bin/find ${workdir}/upgrade/ -type f -depth 1 -maxdepth 1 -name pre-initenv-\* -exec {} \;
	[ -d "${distdir}/upgrade" ] && env workdir="${workdir}" /usr/bin/find ${distdir}/upgrade/ -type f -depth 1 -maxdepth 1 -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}" /usr/bin/find ${distdir}/upgrade/ -type f -depth 1 -maxdepth 1 -name post-patch-\* -exec {} \;
	[ -d "${workdir}/upgrade" ] && env workdir="${workdir}" /usr/bin/find ${workdir}/upgrade/ -type f -depth 1 -maxdepth 1 -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://www.bsdstore.ru/en/installing_cbsd.html"
		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 -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 ^cbsd /etc/master.passwd | cut -d : -f 9 )
				[ "${cbsd_home}" != "${workdir}" ] && pw usermod ${cbsduser} -d ${workdir} >/dev/null 2>&1
			else
				initenv_modify_cbsd_homedir=0
			fi
	esac

	if [ ! -d "${workdir}" ]; then
		/bin/mkdir -m 755 ${workdir}
		if [ $? -ne 0 ]; then
			echo "mkdir error: ${workdir}"
			exit 1
		fi
	fi
	printf "${myversion}" > ${workdir}/ver

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

	${miscdir}/mtree ${workdir}

	env workdir=${workdir} ${distdir}/misc/cmdboot
	_ret=$?
	if [ ${_ret} -ne 0 ]; then
		rm -f ${workdir}/cmd.subr
		echo "initenv cmdboot error: missing necessary binaries"
		exit 1
	fi
	# re-read cmd.subr
	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

}

phase2()
{
	local _dir _ldir _rdir _file _dirhier _d platform

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

	platform=$( uname -s )

	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" ] && ${CC_CMD} ${distdir}/bin/src/cbsdsftp.c -o ${distdir}/bin/cbsdsftp -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdsftp6" ] && ${CC_CMD} ${distdir}/bin/src/cbsdsftp6.c -o ${distdir}/bin/cbsdsftp6 -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdssh" ] && ${CC_CMD} ${distdir}/bin/src/cbsdssh.c -o ${distdir}/bin/cbsdssh -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cbsdssh6" ] && ${CC_CMD} ${distdir}/bin/src/cbsdssh6.c -o ${distdir}/bin/cbsdssh6 -lssh2 -L/usr/local/lib -I/usr/local/include
	[ ! -f "${distdir}/bin/cfetch" ] && ${CC_CMD} ${distdir}/bin/src/cfetch.c -o ${distdir}/bin/cfetch -lfetch
	[ ! -f "${distdir}/sbin/netmask" ] && ${CC_CMD} ${distdir}/sbin/src/netmask.c -o ${distdir}/sbin/netmask

	if [ ! -f "${distdir}/misc/sqlcli" ]; then
		/usr/bin/which pkg-config
		if [ $? -ne 0 ]; 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
		${CC_CMD} ${distdir}/misc/src/sqlcli.c $( pkg-config sqlite3 --cflags --libs ) -lm -o ${distdir}/misc/sqlcli
	fi

	[ ! -f "${distdir}/misc/pwcrypt" ] && ${CC_CMD} ${distdir}/misc/src/pwcrypt.c -lcrypt -o ${distdir}/misc/pwcrypt
	[ ! -f "${distdir}/misc/cbsdlogtail" ] && ${CC_CMD} ${distdir}/misc/src/cbsdlogtail.c -o ${distdir}/misc/cbsdlogtail
	[ ! -f "${distdir}/misc/elf_tables" ] && ${CC_CMD} -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" ] && ${CC_CMD} ${distdir}/misc/src/fmagic.c -lmagic -o ${distdir}/misc/fmagic
	[ ! -f "${distdir}/misc/conv2human" ] && ${CC_CMD} -I/usr/local/include -I/usr/local/include/libelf -L/usr/local/lib ${distdir}/misc/src/conv2human.c -lelf -o ${distdir}/misc/conv2human -lutil
	[ ! -f "${distdir}/misc/cbsd_fwatch" ] && ${CC_CMD} ${distdir}/misc/src/cbsd_fwatch.c -o ${distdir}/misc/cbsd_fwatch
	[ ! -f "${distdir}/misc/cbsd_dot" ] && ${CC_CMD} ${distdir}/misc/src/cbsd_dot.c -o ${distdir}/misc/cbsd_dot
	arch=$( uname -m )
	if [ "${arch}" = "i386" -o "${arch}" = "amd64" ]; then
		[ ! -f "${distdir}/misc/popcnttest" ] && ${CC_CMD} ${distdir}/misc/src/popcnttest.c -o ${distdir}/misc/popcnttest -msse4.2 > /dev/null 2>&1 || /usr/bin/true
	fi
	[ ! -f "${distdir}/misc/chk_arp_byip" ] && ${CC_CMD} ${distdir}/misc/src/chk_arp_byip.c -o ${distdir}/misc/chk_arp_byip
	[ ! -f "${distdir}/misc/cbsdtee" ] && ${CC_CMD} ${distdir}/misc/src/cbsdtee.c -o ${distdir}/misc/cbsdtee
	[ ! -f "${distdir}/misc/daemon" ] && ${CC_CMD} ${distdir}/misc/src/daemon.c -lutil -o ${distdir}/misc/daemon
	[ ! -f "${distdir}/misc/resolv" ] && ${CC_CMD} ${distdir}/misc/src/resolv.c -o ${distdir}/misc/resolv
	[ ! -f "${distdir}/tools/imghelper" ] && ${CC_CMD} ${distdir}/tools/src/imghelper.c -o ${distdir}/tools/imghelper

	case "${platform}" in
		DragonFly|Linux)
			;;
			# not supported yet
		*)
			if [ "${cbsd_initenv_clustering_enabled}" = "1" ]; then
				[ ! -f ${distdir}/tools/racct-jail-statsd ] && ${CC_CMD} ${distdir}/tools/src/racct-jail-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-jail-statsd
				[ ! -f ${distdir}/tools/racct-bhyve-statsd ] && ${CC_CMD} ${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 ] && ${CC_CMD} ${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" ] && ${CC_CMD} ${distdir}/tools/src/racct-jail-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-jail-statsd
				[ ! -f "${distdir}/tools/racct-bhyve-statsd" ] && ${CC_CMD} ${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" ] && ${CC_CMD} ${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" ] && ${CC_CMD} ${distdir}/tools/src/select_jail.c -o ${distdir}/tools/select_jail

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

	if [ ! -f ${distdir}/misc/dump_iscsi_discovery ]; then
		${CC_CMD} -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/misc/src/dump_iscsi_discovery.c -o ${distdir}/misc/src/dump_iscsi_discovery.o
		${CC_CMD} -g -c -Wall -I${distdir}/lib/simplexml ${distdir}/lib/simplexml/simplexml.c -o ${distdir}/lib/simplexml/simplexml.o
		${CC_CMD} -g -o ${distdir}/misc/dump_iscsi_discovery ${distdir}/misc/src/dump_iscsi_discovery.o ${distdir}/lib/simplexml/simplexml.o
		/bin/rm -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 [ -f ${distdir}/misc/src/sipcalc/Makefile ]; then
			make -C ${distdir}/misc/src/sipcalc
			installne "-o ${cbsduser} -g ${cbsduser} -m 555" ${distdir}/misc/src/sipcalc/sipcalc ${distdir}/misc/sipcalc
			make -C ${distdir}/misc/src/sipcalc clean
		fi
	fi

	if [ ! -f ${distdir}/misc/ipv6range ]; then
		${CC_CMD} -o ${distdir}/misc/ipv6range ${distdir}/misc/src/ipv6range.c
	fi
	if [ "${platform}" != "DragonFly" ]; then
		[ ! -f "${distdir}/misc/next-vale-port" ] && ${CC_CMD} -o ${distdir}/misc/next-vale-port ${distdir}/misc/src/next-vale-port.c
		[ ! -f "${distdir}/tools/vale-ctl" ] && ${CC_CMD} ${distdir}/tools/src/vale-ctl.c -o ${distdir}/tools/vale-ctl
		[ ! -f "${distdir}/tools/nic_info" ] && ${CC_CMD} ${distdir}/tools/src/nic_info.c -o ${distdir}/tools/nic_info
		[ ! -f "${distdir}/tools/bridge" ] && ${CC_CMD} ${distdir}/tools/src/bridge.c -o ${distdir}/tools/bridge
	fi
	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
		${CC_CMD} ${distdir}/misc/src/sqlcli.c -lsqlite3 -L/usr/local/lib -I/usr/local/include -o ${distdir}/misc/sqlcli
		[ -f "${distdir}/bin/cbsdsh/cbsd" ] && /usr/bin/install -m 0500 -s -o ${cbsduser} -g ${cbsduser} -m 500 ${distdir}/bin/cbsdsh/cbsd /usr/local/bin/cbsd
		/usr/sbin/chown ${cbsduser}:${cbsduser} /usr/local/bin/cbsd
	fi

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

	for _d in ${_dirhier}; do
		_ldir="${workdir}/${_d}"
		_rdir="${distdir}/${_d}"
		for _file in $( /usr/bin/find ${_rdir} -depth 1 -maxdepth 1 -type f -exec /usr/bin/basename {} \; ); 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 > ${etcdir}/cbsd_sudoers <<EOF
Defaults     env_keep += "workdir DIALOG NOCOLOR CBSD_RNODE"
Cmnd_Alias   CBSD_CMD = ${sudoexecdir}/*,/usr/local/cbsd/sudoexec/*
${cbsduser}   ALL=(ALL) NOPASSWD:SETENV: CBSD_CMD
EOF

	for _d in ${_dirhier}; do
		_ldir="${workdir}/${_d}"
		_rdir="${distdir}/${_d}"
		for _file in $( /usr/bin/find ${_rdir} -depth 1 -maxdepth 1 -type f -exec /usr/bin/basename {} \; ); do
			if [ ! -f "${_ldir}/${_file}" ]; then
				[ ! -d ${_ldir} ] && mkdir -p ${_ldir}
				/usr/bin/install -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

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

	#    [ -d ${sshdir} ] || /bin/mkdir -m 0700 ${sshdir}
	#    [ -d "${sshdir}/sockets" ] || /bin/mkdir -m 0700 "${sshdir}/sockets"
	[ -f "${sshdir}/config" ] || installne "-o ${cbsduser} -g ${cbsduser} -m 644" ${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" ] && /bin/mkdir -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" ] && /bin/mkdir -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" ] && /bin/mkdir -p ${sharedir}/${platform}-jail-puppet-skel && /bin/cp -a ${distdir}/share/${platform}-jail-puppet-skel/* ${sharedir}/${platform}-jail-puppet-skel/
	[ ! -d "${sharedir}/${platform}-jail-puppet-skel/rc.d" -a -d "${distdir}/share/${platform}-jail-puppet-skel/etc" ] && /bin/mkdir -p ${sharedir}/${platform}-jail-puppet-skel/etc/rc.d && /bin/cp -a ${distdir}/share/${platform}-jail-puppet-skel/etc/rc.d/* ${sharedir}/${platform}-jail-puppet-skel/etc/rc.d/
	[ -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
#		/bin/mkdir -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
3		/bin/mkdir -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
#		/bin/mkdir -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-centos-7-system-skel/tests/00.check_distribution.sh" -a -d "${distdir}/share/${platform}-jail-centos-7-system-skel" ]; then
#		/bin/mkdir -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-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}/jail-system-default" -a -d "${distdir}/share/jail-system-default" ] && /bin/cp -a ${distdir}/share/jail-system-default ${sharedir}/
	[ ! -d "${sharedir}/bhyve-system-default" -a -d "${distdir}/share/bhyve-system-default" ] && /bin/cp -a ${distdir}/share/bhyve-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" ] && /bin/mkdir -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=$( /bin/hostname )

		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 ${p}
		if getyesno "Shall i modify the /etc/rc.conf to set new hostname value?: ${p}" ${initenv_modify_rcconf_hostname}; then
			initenv_modify_rcconf_hostname=1
			${SYSRC_CMD} -vf /etc/rc.conf hostname="${p}"
		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} | /usr/bin/tr "," " "); 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}
				/bin/cat ${sharedir}/${platform}-jail-skel/etc/resolv.conf >> ${TMPR}
				/bin/mv ${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"

	#system information
	. ${toolsdir}/sysinv
	update_netinfo

	init_items_desc
	init_items_default

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

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

	/bin/chmod 0660 ${dbdir}/inv.${nodename}.sqlite && /usr/sbin/chown ${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-vnetnic.schema vnetnic
	env workdir=${workdir} /usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-vmpackages.schema vmpackages
	_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', '1g', '10g', '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}
	/bin/ln -sfh inv.${nodename}.sqlite local.sqlite

	_myfs="ufs"
	zfsfeat=0

	if kldstat -qm zfs >/dev/null 2>&1; then
		/sbin/zfs list ${jaildatadir} > /dev/null 2>&1
		if [ $? -eq 0 ]; then
			_myfs="zfs"
			zfsfeat=1
		else
			zfsfeat=0
			${miscdir}/sqlcli ${dbdir}/local.sqlite UPDATE local SET zfsfeat=\"0\"
		fi
	fi

	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
		. ${INITCFG}
		_uncfg=$( ${GREP_CMD} -v '^#' ${INITCFG} | /usr/bin/cut -d '=' -f1 | /usr/bin/xargs )
	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
					nat_enable="pf"
					configure_nat
				fi

				if [ -n "${INITCFG_PRESEED}" ]; then
					${SYSRC_CMD} -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://bsdstore.ru\"
	${miscdir}/sqlcli ${dbdir}/local.sqlite UPDATE local SET workdir=\"${workdir}\"

	_ret=$( sysctl -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"
	# Overwrite $platform to TrueOS if we have TrueOS-specific dirs
	[ -d "/usr/local/etc/trueos" -a -d "/usr/local/share/trueos" ] && platform="TrueOS"

	ipfw_enable="${_ret}"
	fs="${_myfs}"

	for i in ipfw_enable fs jail_interface nodedescr nodename hostname vnet racct platform node_ip4_active node_ip6_active nodeip natip; do
		T=
		eval T="\$$i"
		${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"
			${SYSRC_CMD} -qf ${INITCFG_PRESEED} ${i}="${T}" >/dev/null
		done
	fi

	local FILES="descr role domain notes location"
	for i in $FILES; do
		[ ! -f "${workdir}/${i}" ] && /usr/bin/touch ${workdir}/node.${i} && /usr/sbin/chown 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 -p -m 0775 ${_i}
			chown 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}"

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

	[ ! -f "${etcdir}/modules.conf" ] && return 0
	# Deinstall module first
	for _lnk in $( /usr/bin/find ${moduledir} -type l -depth 1 -maxdepth 1 ); do
		_dst=$( /usr/bin/readlink ${_lnk} )
		_dst=$( /usr/bin/dirname ${_dst} )
		#append slash for next excluding in _modulename
		_moduledir="${distmoduledir}/"
		_modulename="${_dst#$_moduledir}"
		_my_module=$( echo ${_modulename} | sed '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}"
			/bin/rm -f ${_lnk}
			${SYSRC_CMD} -qf ${inventory} mod_${_my_module}_enabled="NO" > /dev/null 2>&1
		fi
	done

	# Install module
	for _i in $( /bin/cat ${etcdir}/modules.conf ); do
		[ ! -f "${distmoduledir}/${_i}/securecmd" ] && continue
		. ${distmoduledir}/${_i}/securecmd
		_my_module=$( echo ${_i} | sed 's:\.d$::g' )	# strip .d$
		for _cmd in ${SECCMD}; do
			if [ ! -h "${moduledir}/${_cmd}" ]; then
				/bin/ln -sfh ${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 "-" "_" )	# cast '-' to '_'
		${SYSRC_CMD} -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 $( /bin/cat ${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}" && /bin/rm -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}" && /bin/rmdir ${workdir}/${i}
	done
	printf "${N0_COLOR}"
}

post_message()
{
	[ ${first_init} -eq 0 ] && return 0
	unset NOCOLOR
	. ${subrdir}/ansiicolor.subr
	ECHO="echo -e"
	${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}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} "  ${H3_COLOR}Enjoy CBSD!${N0_COLOR}"
	${ECHO}
}

############ start locking section #############
start()
{
	if [ -n "${INITCFG}" ]; then
		inter=0
		ALWAYS_YES=1
		. "${INITCFG}" 2>/dev/null
	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


	/bin/cat << 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}" ] && . /etc/rc.conf
	[ ! -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 | /usr/bin/wc -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
				${SYSRC_CMD} -vf /etc/rc.conf cbsd_workdir="${workdir}"
			else
				initenv_modify_rcconf_cbsd_workdir=0
				${SYSRC_CMD} -qf ${workdir}/rc.conf cbsd_workdir="${workdir}"
			fi
		fi
	fi

	#echo "if getyesno shall: ${initenv_modify_rcconf_cbsd_workdir}"
	#exit 0


	if [ $( ${GREP_CMD} ^cbsd_workdir= /etc/rc.conf ${workdir}/rc.conf | /usr/bin/wc -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
			${SYSRC_CMD} -vf /etc/rc.conf cbsd_workdir="${workdir}"
		else
			initenv_modify_rcconf_cbsd_workdir=0
			${SYSRC_CMD} -qf ${workdir}/rc.conf cbsd_workdir="${workdir}"
		fi
	fi

	if [ ${first_init} -eq 1 ]; then
		if [ $( ${GREP_CMD} ^preseedinit= ${workdir}/rc.conf | /usr/bin/wc -l ) = 0 ]; then
			if [ ${inter} -eq 1 ]; then
				INITCFG_PRESEED=$( mktemp )
				cat > ${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}
	# end of Inventory
	phase7
	phase8
	phase9

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

	if [ $( ${GREP_CMD} ^cbsdd_enable= /etc/rc.conf ${workdir}/rc.conf | /usr/bin/wc -l ) = 0 ]; then
		if getyesno "Shall i modify the /etc/rc.conf to sets cbsdd_enable=YES ?" ${initenv_modify_rcconf_cbsd_enable}; then
			initenv_modify_rcconf_cbsd_enable=1
			${SYSRC_CMD} -vf /etc/rc.conf cbsdd_enable=YES
		else
			initenv_modify_rcconf_cbsd_enable=0
			${SYSRC_CMD} -qf ${workdir}/rc.conf cbsdd_enable="NO"
		fi
	fi

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

	if [ $( ${GREP_CMD} ^rcshutdown_timeout= /etc/rc.conf ${workdir}/rc.conf | /usr/bin/wc -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
			${SYSRC_CMD} -vf /etc/rc.conf rcshutdown_timeout="900"
			rcshutdown_timeout="900"
		else
			initenv_modify_rcconf_rcshutdown_timeout=0
			${SYSRC_CMD} -qf ${workdir}/rc.conf rcshutdown_timeout="900"
		fi
	fi

	kern_init_shutdown_timeout=$( /sbin/sysctl -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 | /usr/bin/wc -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"
				/sbin/sysctl -qw kern.init_shutdown_timeout="900"
			else
				initenv_modify_syctl_rcshutdown_timeout=0
				${SYSRC_CMD} -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"
			${SYSRC_CMD} -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 ${INITCFG_PRESEED} /tmp/prs.txt

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

		fi
		rm -f ${INITCFG_PRESEED}

		${SYSRC_CMD} -qf ${workdir}/rc.conf preseedinit="${answ}" > /dev/null 2>&1
	fi

	exit 0
}

# export LOCK_CMD
init_lock()
{
	local _lock_cmd
	LOCK_CMD=

	_lock_cmd=$( which lockf 2>/dev/null )

	if [ -n "${_lock_cmd}" -a -x "${_lock_cmd}" ]; then
		LOCK_CMD="${_lock_cmd} -t0 -s "
	else
		_lock_cmd=$( which 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 ###
init_lock

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

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

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

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

platform=$( uname -s )
arch=$( uname -p )

# Overwrite $platform to HardenedBSD if we have /usr/sbin/hbsd-update:
[ -e "/usr/sbin/hbsd-update" ] && platform="HardenedBSD"
# Overwrite $platform to TrueOS if we have TrueOS-specific dirs
[ -d "/usr/local/etc/trueos" -a -d "/usr/local/share/trueos" ] && platform="TrueOS"

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

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