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