Blame subr.ex/ex_init.subr

e9fa07
#
8d7a8a
# Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 LucĂ­a Andrea Illanes Albornoz <lucia@luciaillanes.de>
e9fa07
# set +o errexit -o noglob -o nounset is assumed.
e9fa07
#
e9fa07
e9fa07
exp_setrstatus() {
e9fa07
	local _epsrs_rstatus="${1#\$}" _epsrs_status="${2}";
e9fa07
	eval ${_epsrs_rstatus}=\"${_epsrs_status}\";
e9fa07
	return 0;
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_env() - initialise build environment
7d702f
# @_rstatus:		out reference to variable of status string on failure
7d702f
# @_rhname:		out reference to variable of build hostname
7d702f
# @_ruser:		out reference to variable of build user
e9fa07
# @_name_base:		base name for messages and theme file(s)
e9fa07
#
99f4d8
# Returns:		zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_env() {
e9fa07
	local	_eie_rstatus="${1#\$}" _eie_rhname="${2#\$}" _eie_ruser="${3#\$}"	\
e9fa07
		_eie_name_base="${4}"							\
e9fa07
		_eie_fname="" _eie_lang="${LANG:-C}" _eie_lang_="" _eie_name=""		\
e9fa07
		_eie_rc=0;
e9fa07
	_eie_lang="${_eie_lang%%_*}";
e9fa07
e9fa07
	if ! cd "${0%/*}"; then
e9fa07
		_eie_rc=1;
e9fa07
		exp_setrstatus "${_eie_rstatus}" 'failed to change working directory to \`'"${0%/*}"''\''.';
e9fa07
	elif ! umask 022; then
e9fa07
		_eie_rc=1;
e9fa07
		exp_setrstatus "${_eie_rstatus}" 'failed to set umask(2).';
e9fa07
	elif ! eval ${_eie_rhname}=\"\$\(hostname\)\"; then
e9fa07
		_eie_rc=1;
e9fa07
		exp_setrstatus "${_eie_rstatus}" 'failed to obtain hostname.';
e9fa07
	elif ! eval ${_eie_ruser}=\"\$\(id -nu\)\"; then
e9fa07
		_eie_rc=1;
e9fa07
		exp_setrstatus "${_eie_rstatus}" 'failed to obtain username.';
e9fa07
	else
e9fa07
		for _eie_fname in				\
e9fa07
				$(find subr.ex -name *.subr)	\
e9fa07
				$(find subr.pkg -name *.subr)	\
e9fa07
				$(find subr.rtl -name *.subr)	\
e9fa07
				"etc/${_eie_name_base}.theme"	\
e9fa07
				;
e9fa07
		do
e9fa07
			if ! . "${_eie_fname}"; then
e9fa07
				_eie_rc=1;
e9fa07
				exp_setrstatus "${_eie_rstatus}" 'failed to source \`'"${_eie_fname}"''\''.';
e9fa07
				break;
e9fa07
			fi;
e9fa07
		done;
e9fa07
e9fa07
		if [ "${_eie_rc}" -eq 0 ]; then
e9fa07
			if [ -e "${_eie_name_base}.local" ]; then
e9fa07
				if ! . "${_eie_name_base}.local"; then
e9fa07
					_eie_rc=1;
e9fa07
					exp_setrstatus "${_eie_rstatus}" 'failed to source \`'"${_eie_name_base}"'.local'\''.';
e9fa07
				fi;
e9fa07
			fi;
e9fa07
		fi;
e9fa07
e9fa07
		if [ "${_eie_rc}" -eq 0 ]; then
e9fa07
			for _eie_name in ${_eie_name_base} rtl; do
e9fa07
				for _eie_lang_ in ${_eie_lang} C; do
e9fa07
					_eie_fname="etc/${_eie_name}.msgs.${_eie_lang_}";
e9fa07
					if [ -e "${_eie_fname}" ]; then
e9fa07
						if ! . "${_eie_fname}"; then
e9fa07
							_eie_rc=1;
e9fa07
							exp_setrstatus "${_eie_rstatus}" 'failed to source \`'"${_eie_fname}"''\''.';
e9fa07
							break;
e9fa07
						fi;
e9fa07
e9fa07
						if [ -e "${_eie_fname}.local" ]; then
e9fa07
							if ! . "${_eie_fname}.local"; then
e9fa07
								_eie_rc=1;
e9fa07
								exp_setrstatus "${_eie_rstatus}" 'failed to source \`'"${_eie_fname}"'.local'\''.';
e9fa07
							fi;
e9fa07
						fi;
e9fa07
						break;
e9fa07
					fi;
e9fa07
				done;
e9fa07
e9fa07
				if [ "${_eie_rc}" -ne 0 ]; then
e9fa07
					break;
e9fa07
				fi;
e9fa07
			done;
e9fa07
		fi;
e9fa07
	fi;
e9fa07
	export LANG=C LC_ALL=C;
e9fa07
e9fa07
	return "${_eie_rc}";
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_getopts() - process command-line arguments
7d702f
# @_rstatus:	out reference to variable of status string on failure
e9fa07
# @_fn:		reference to function called to process command-line argument
e9fa07
# @_optstring:	getopts(1) optstring
e9fa07
# @...:		command-line arguments as "${@}"
e9fa07
#
99f4d8
# Returns:	zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_getopts() {
e9fa07
	local	_eig_rstatus="${1#\$}" _eig_fn="${2}" _eig_optstring="${3}"	\
e9fa07
		_eig_arg="" _eig_fn_rc=0 _eig_opt="" _eig_shiftfl=0		\
e9fa07
		OPTARG="" OPTIND=0;
e9fa07
	shift 3;
e9fa07
e9fa07
	if ! "${_eig_fn}" init "${_eig_rstatus}"; then
e9fa07
		return 1;
e9fa07
	fi;
e9fa07
e9fa07
	while [ "${#}" -gt 0 ]; do
e9fa07
		case "${1}" in
e9fa07
		--*)
3a7f9a
			"${_eig_fn}" longopt "${_eig_rstatus}" "${1}" ${2:-};
e9fa07
			_eig_fn_rc="${?}";
e9fa07
e9fa07
			case "${_eig_fn_rc}" in
e9fa07
			0)	;;
e9fa07
			1)	return 1; ;;
e9fa07
e9fa07
			*)	shift "$((${_eig_fn_rc} - 1))";
e9fa07
				continue; ;;
e9fa07
			esac;
e9fa07
			;;
e9fa07
		esac;
e9fa07
7b6d2f
		OPTIND=0;
e9fa07
		if getopts "${_eig_optstring}" _eig_opt; then
e9fa07
			"${_eig_fn}" opt "${_eig_rstatus}" "${_eig_opt}" "${OPTARG:-}" "${@}";
e9fa07
			_eig_fn_rc="${?}";
e9fa07
e9fa07
			case "${_eig_fn_rc}" in
e9fa07
			0)	;;
e9fa07
			1)	return 1; ;;
e9fa07
e9fa07
			*)	shift "$((${_eig_fn_rc} - 1))";
e9fa07
				continue; ;;
e9fa07
			esac;
e9fa07
		else
e9fa07
			"${_eig_fn}" nonopt "${_eig_rstatus}" "${@}";
e9fa07
			_eig_fn_rc="${?}";
e9fa07
e9fa07
			case "${_eig_fn_rc}" in
e9fa07
			0)	;;
e9fa07
			1)	return 1; ;;
e9fa07
e9fa07
			*)	shift "$((${_eig_fn_rc} - 1))";
e9fa07
				continue; ;;
e9fa07
			esac;
e9fa07
		fi;
e9fa07
	done;
e9fa07
e9fa07
	if ! "${_eig_fn}" done "${_eig_rstatus}"; then
e9fa07
		return 1;
e9fa07
	fi;
e9fa07
e9fa07
	return 0;
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_help() - display usage screen and exit if requested in command-line arguments
7d702f
# @_rstatus:	out reference to variable of status string on failure
e9fa07
# @_args_long:	optional list of long (prefixed with `--') arguments
e9fa07
# @_name_base:	base name for usage screen file
e9fa07
# @_optstring:	getopts(1) optstring
e9fa07
#
99f4d8
# Returns:	zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_help() {
e9fa07
	local	_eih_rstatus="${1#\$}" _eih_args_long="${2}"	\
e9fa07
		_eih_name_base="${3}" _eih_optstring="${4}"	\
15ddac
		_eih_arg_long="" _eih_opt="" _eih_shiftfl=0	\
15ddac
		OPTIND;
e9fa07
	shift 4;
e9fa07
e9fa07
	while [ "${#}" -gt 0 ]; do
e9fa07
		case "${1}" in
a2d9a2
			-h)
a2d9a2
			if [ -t 1 ]; then
a2d9a2
				cat "etc/${_eih_name_base}.usage.short";
a2d9a2
			else
a2d9a2
				sed 's/?\[[0-9]\+m//g' "etc/${_eih_name_base}.usage.short";
a2d9a2
			fi;
a2d9a2
			exit 0;
a2d9a2
			;;
a2d9a2
a2d9a2
		--help)
e9fa07
			if [ -t 1 ]; then
e9fa07
				cat "etc/${_eih_name_base}.usage";
e9fa07
			else
e9fa07
				sed 's/?\[[0-9]\+m//g' "etc/${_eih_name_base}.usage";
e9fa07
			fi;
e9fa07
			exit 0;
e9fa07
			;;
e9fa07
e9fa07
		*=*)	shift; continue;
e9fa07
			;;
e9fa07
e9fa07
		*)	_eih_shiftfl=0;
e9fa07
			for _eih_arg_long in ${_eih_args_long}; do
e9fa07
				if [ "${_eih_arg_long}" = "${1}" ]; then
e9fa07
					_eih_shiftfl=1;
e9fa07
				fi;
e9fa07
			done;
e9fa07
			if [ "${_eih_shiftfl}" = 1 ]; then
e9fa07
				shift; continue;
e9fa07
			fi;
e9fa07
			;;
e9fa07
		esac;
e9fa07
15ddac
		OPTIND=0;
e9fa07
		if getopts "${_eih_optstring}" _eih_opt 2>/dev/null; then
e9fa07
			case "${_eih_opt}" in
e9fa07
			h)
e9fa07
				if [ -t 1 ]; then
a2d9a2
					cat "etc/${_eih_name_base}.usage.short";
e9fa07
				else
a2d9a2
					sed 's/?\[[0-9]\+m//g' "etc/${_eih_name_base}.usage.short";
e9fa07
				fi;
e9fa07
				exit 0;
e9fa07
				;;
e9fa07
			esac;
e9fa07
			shift $((${OPTIND}-1)); OPTIND=1;
e9fa07
		else
e9fa07
			shift;
e9fa07
		fi;
e9fa07
	done;
e9fa07
e9fa07
	return 0;
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_files() - initialise build files
7d702f
# @_rstatus:				out reference to variable of status string on failure
7d702f
# @_rclean_builds:			in reference to variable of -C argument value
7d702f
# @_rdist:				in reference to variable of -D argument value
e9fa07
# @_build_log_fname:			absolute pathname to build log file
e9fa07
# @_build_log_last_fname:		absolute pathname to last build log file
e9fa07
# @_build_status_in_progress_fname:	absolute pathname to build-in-progress status file
e9fa07
# @_check_path_vars:			list of pathname variables to check
e9fa07
# @_clear_env_vars_except:		list of environment variables to not unset when clearing the environment
e9fa07
# @_clear_prefix_paths:			list of directory pathnames to clear in the top-level prefix
ab21e5
# @_rpm_semaphore:			absolute pathname to rpmbuild(1) parallel jobs count semaphore
e9fa07
# @_dlcachedir:				absolute pathname to download cache directory
e9fa07
# @_prefix:				absolute pathname to top-level prefix
e9fa07
# @_prefix_rpm:				absolute pathname to RPM files prefix
e9fa07
# @_workdir:				absolute pathname to build-specific temporary directory
e9fa07
#
99f4d8
# Returns:				zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_files() {
e9fa07
	local	_eif_rstatus="${1#\$}" _eif_rclean_builds="${2#\$}" _eif_rdist="${3#\$}"	\
e9fa07
		_eif_build_log_fname="${4}" _eif_build_log_last_fname="${5}"			\
e9fa07
		_eif_build_status_in_progress_fname="${6}" _eif_check_path_vars="${7}"		\
e9fa07
		_eif_clear_env_vars_except="${8}" _eif_clear_prefix_paths="${9}"		\
ab21e5
		_eif_rpm_semaphore="${10}" _eif_dlcachedir="${11}" _eif_prefix="${12}"		\
ab21e5
		_eif_prefix_rpm="${13}" _eif_workdir="${14}"					\
e9fa07
		_eif_log_last_fname="" _eif_log_last_num=1 _eif_rc=0;
e9fa07
e9fa07
	if ! rtl_fileop mkdir "${_eif_dlcachedir}" "${_eif_workdir}"\
e9fa07
	|| rtl_lmatch "${_eif_rdist}" "rpm" ","\
e9fa07
	&& ! rtl_fileop mkdir "${_eif_prefix_rpm}"; then
e9fa07
		_eif_rc=1;
e9fa07
		rtl_setrstatus "${_eif_rstatus}" 'cannot create build directories.';
e9fa07
	elif [ -e "${_eif_build_status_in_progress_fname}" ]; then
e9fa07
		_eif_rc=1;
e9fa07
		rtl_setrstatus "${_eif_rstatus}" 'another build targeting this architecture and build type is currently in progress.';
e9fa07
	elif ! rtl_clean_env "${_eif_clear_env_vars_except}"; then
e9fa07
		_eif_rc=1;
e9fa07
		rtl_setrstatus "${_eif_rstatus}" 'failed to clean environment.';
e9fa07
	elif ! rtl_check_path_vars "${_eif_rstatus}" "${_eif_check_path_vars}"; then
e9fa07
		_eif_rc=1;
e9fa07
	else
02bbcd
		export LC_ALL="${LC_ALL:-C}";
e9fa07
		export TMP="${_eif_workdir}" TMPDIR="${_eif_workdir}";
e9fa07
		touch "${_eif_build_status_in_progress_fname}";
e9fa07
e9fa07
		if [ -e "${_eif_build_log_fname}" ]; then
e9fa07
			while [ -e "${_eif_build_log_fname}.${_eif_log_last_num}" ]; do
e9fa07
				: $((_eif_log_last_num+=1));
e9fa07
			done;
e9fa07
e9fa07
			_eif_log_last_fname="${_eif_build_log_fname}.${_eif_log_last_num}";
e9fa07
			rtl_fileop mv "${_eif_build_log_fname}" "${_eif_log_last_fname}";
e9fa07
			rtl_fileop ln_symbolic "${_eif_log_last_fname}" "${_eif_build_log_last_fname}";
e9fa07
		fi;
e9fa07
ab21e5
		rtl_fileop touch "${_eif_build_log_fname}";
ab21e5
		rtl_log_set_fname "${_eif_build_log_fname}";
ab21e5
ab21e5
		rtl_fileop rm "${_eif_rpm_semaphore}";
ab21e5
e9fa07
		if rtl_lmatch "${_eif_rclean_builds}" $"prefix" ","; then
e9fa07
			trap "rm -f \"${_eif_build_status_in_progress_fname}\" 2>/dev/null;
e9fa07
4243a1
			rtl_log_msgV \"fatalexit\" \"${MSG_build_aborted}\"" HUP INT TERM USR1 USR2;
4243a1
			rtl_log_msgV "info" "${MSG_build_clean_prefix}";
e9fa07
e9fa07
			for _eif_pname in ${_eif_clear_prefix_paths}; do
e9fa07
				if ! rtl_fileop rm "${_eif_prefix}/${_eif_pname}"; then
e9fa07
					_eif_rc=1;
e9fa07
					rtl_setrstatus "${_eif_rstatus}" 'failed to remove \`'"${_eif_prefix:+${_eif_prefix}/}${_eif_pname}'"'.';
e9fa07
					break;
e9fa07
				fi;
e9fa07
			done;
e9fa07
e9fa07
			trap - HUP INT TERM USR1 USR2;
e9fa07
		fi;
e9fa07
308fa7
		export PATH="${_eif_prefix}/localcross/bin${PATH:+:${PATH}}";
e9fa07
		export PATH="${_eif_prefix}/bin${PATH:+:${PATH}}";
e9fa07
	fi;
e9fa07
e9fa07
	return "${_eif_rc}";
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_logging() - initialise build logging
7d702f
# @_rstatus:		out reference to variable of status string on failure
7d702f
# @_rverbose_tags:	in reference toout variable of -V argument value
e9fa07
# @_verbose:		-[vV] argument value
e9fa07
#
99f4d8
# Returns:		zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_logging() {
e9fa07
	local	_eil_rstatus="${1#\$}" _eil_rverbose_tags="${2#\$}" _eil_verbose="${3}"	\
e9fa07
		_eil_tag="" _eil_tags="" _eil_tags_enable="" _eil_rc=0;
e9fa07
e9fa07
	rtl_log_clear_tags;
e9fa07
	case "${_eil_verbose}" in
e9fa07
e9fa07
	0)	if eval [ \"\${#${_eil_rverbose_tags}}\" -eq 0 ]; then
4243a1
			rtl_log_enable_tagsV "${LOG_TAGS_normal}";
e9fa07
		fi;
e9fa07
		;;
e9fa07
4243a1
	1)	rtl_log_enable_tagsV "${LOG_TAGS_verbose}"; ;;
e9fa07
e9fa07
	*)	_eil_rc=1;
e9fa07
		rtl_setrstatus "${_eil_rstatus}" 'invalid verbosity level (max. -v)';
e9fa07
		;;
e9fa07
e9fa07
	esac;
e9fa07
e9fa07
	if [ "${_eil_rc}" -eq 0 ]; then
e9fa07
		eval _eil_tags="\${${_eil_rverbose_tags}}";
e9fa07
		case "${_eil_tags}" in
e9fa07
4243a1
		+*)	rtl_log_enable_tagsV "${LOG_TAGS_normal}";
e9fa07
			eval ${_eil_rverbose_tags}="\${${_eil_rverbose_tags}#+}";
e9fa07
			;;
e9fa07
e9fa07
		*)	;;
e9fa07
e9fa07
		esac;
e9fa07
e9fa07
		rtl_llift2 "${_eil_rverbose_tags}" \$_eil_tags "," " ";
e9fa07
e9fa07
		for _eil_tag in ${_eil_tags}; do
e9fa07
			case "${_eil_tag}" in
e9fa07
4243a1
			all)		rtl_log_enable_tagsV "${LOG_TAGS_all}"; ;;
e9fa07
e9fa07
			clear|none)	rtl_log_clear_tags; ;;
e9fa07
4243a1
			normal)		rtl_log_enable_tagsV "${LOG_TAGS_normal}"; ;;
e9fa07
4243a1
			verbose)	rtl_log_enable_tagsV "${LOG_TAGS_verbose}"; ;;
e9fa07
e9fa07
			*)		rtl_lsearch_patternl2 \$LOG_TAGS_all \$_eil_tags_enable "${_eil_tag}" ",";
e9fa07
					if [ "${#_eil_tags_enable}" -gt 0 ]; then
4243a1
						rtl_log_enable_tagsV "${_eil_tags_enable}";
e9fa07
					else
e9fa07
						_eil_rc=1;
e9fa07
						rtl_setrstatus "${_eil_rstatus}" 'invalid log tag or tag pattern \`'"${_eil_tag}"''\''.';
e9fa07
						break;
e9fa07
					fi;
e9fa07
					;;
e9fa07
e9fa07
			esac;
e9fa07
		done;
e9fa07
	fi;
e9fa07
e9fa07
	return "${_eil_rc}";
e9fa07
};
e9fa07
e9fa07
#
e9fa07
# ex_init_prereqs() - initialise build prerequisite commands
7d702f
# @_rstatus:	out reference to variable of status string on failure
e9fa07
# @_prereqs:	list of prerequisite commands
e9fa07
#
99f4d8
# Returns:	zero (0) on success, non-zero (>0) on failure
e9fa07
#
e9fa07
ex_init_prereqs() {
e9fa07
	local	_eip_rstatus="${1#\$}" _eip_prereqs="${2}"	\
e9fa07
		_eip_rc=0;
e9fa07
4243a1
	if ! rtl_check_prereqsV "${_eip_rstatus}" ${_eip_prereqs}; then
e9fa07
		_eip_rc=1;
e9fa07
	elif ! awk -V 2>/dev/null | grep -q "^GNU Awk "; then
e9fa07
		_eip_rc=1;
e9fa07
		rtl_setrstatus "${_eip_rstatus}" 'awk(1) in \$PATH must be GNU Awk.';
141b0f
	elif ! (FNAME="$(mktemp)" && { trap "rm -f \"\${FNAME}\"" EXIT HUP INT TERM USR1 USR2;	\
e9fa07
			sed -i'' -e '' "${FNAME}" >/dev/null 2>&1; });
e9fa07
	then
e9fa07
		_eip_rc=1;
e9fa07
		rtl_setrstatus "${_eip_rstatus}" 'sed(1) in \${PATH} does not support the \`-i'\'' option.';
e9fa07
	fi;
e9fa07
e9fa07
	return "${_eip_rc}";
e9fa07
};
e9fa07
3a7f9a
#
3a7f9a
# ex_init_theme() - initialise theme
7d702f
# @_rstatus:	out reference to variable of status string on failure
d982c0
# @_hname:	build hostname
3a7f9a
# @_name_base:	base name for theme file(s)
3a7f9a
# @_theme:	theme name
3a7f9a
#
99f4d8
# Returns:	zero (0) on success, non-zero (>0) on failure
3a7f9a
#
3a7f9a
ex_init_theme() {
d982c0
	local	_eit_rstatus="${1#\$}" _eit_hname="${2}" _eit_name_base="${3}" _eit_theme="${4}"	\
3a7f9a
		_eit_rc=0 _eit_theme_fname="";
3a7f9a
d982c0
	if [ "${_eit_theme:+1}" = 1 ]; then
d982c0
		_eit_theme_fname="etc/${_eit_name_base}.${_eit_theme}.theme";
d982c0
	else
d982c0
		_eit_theme_fname="etc/${_eit_name_base}.theme.host.${_eit_hname}";
d982c0
		if ! [ -e "${_eit_theme_fname}" ]; then
d982c0
			_eit_theme_fname="etc/${_eit_name_base}.theme";
d982c0
		fi;
d982c0
	fi;
d982c0
3a7f9a
	if ! [ -e "${_eit_theme_fname}" ]; then
3a7f9a
		_eit_rc=1;
3a7f9a
		exp_setrstatus "${_eit_rstatus}" 'failed to source \`'"${_eit_theme_fname}"''\''.';
3a7f9a
	else
3a7f9a
		. "${_eit_theme_fname}";
3a7f9a
	fi;
3a7f9a
3a7f9a
	return "${_eit_rc}";
3a7f9a
};
3a7f9a
e9fa07
# vim:filetype=sh textwidth=0