summaryrefslogtreecommitdiffhomepage
path: root/subr.ex/ex_init.subr
diff options
context:
space:
mode:
Diffstat (limited to 'subr.ex/ex_init.subr')
-rw-r--r--subr.ex/ex_init.subr449
1 files changed, 449 insertions, 0 deletions
diff --git a/subr.ex/ex_init.subr b/subr.ex/ex_init.subr
new file mode 100644
index 00000000..5dc4f857
--- /dev/null
+++ b/subr.ex/ex_init.subr
@@ -0,0 +1,449 @@
+#
+# 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 LC_ALL="${LC_ALL:-C}";
+ 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}/localcross/bin${PATH:+:${PATH}}";
+ 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 to out 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 HUP INT TERM USR1 USR2; \
+ 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