# # Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 LucĂ­a Andrea Illanes Albornoz # set +o errexit -o noglob -o nounset is assumed. # # # rtl_check_prereqsV() - check for existence of list of commands # @_rstatus: out reference to status string # @...: commands list as positional parameters # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_check_prereqsV() { local _rcp_rstatus="${1#\$}" \ _rcp_cmd="" _rcp_cmds_missing="" _rcp_rc=0; shift; for _rcp_cmd in "${@}"; do if ! which "${_rcp_cmd}" >/dev/null 2>&1; then _rcp_cmds_missing="${_rcp_cmds_missing:+${_rcp_cmds_missing} }${_rcp_cmd}"; fi; done; if [ "${_rcp_cmds_missing:+1}" = 1 ]; then _rcp_rc=1; rtl_setrstatus "${_rcp_rstatus}" 'Error: missing prerequisite package(s): '"${_rcp_cmds_missing}"; fi; return "${_rcp_rc}"; }; # # rtl_clean_env() - unset environment variables w/ exceptions # @_env_vars_except: list of environment variables to keep # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_clean_env() { local _rce_env_vars_except="${1}" \ _rce_env_var="" _rce_env_vars="" _rce_env_vars_unset=""; _rce_env_vars="$(export | sed -ne '/^export/{s/^export //;s/=.*$//p}')"; for _rce_env_var in ${_rce_env_vars}; do if [ "${_rce_env_var#DEFAULT_}" != "${_rce_env_var}" ]\ || [ "${_rce_env_var#PKG_}" != "${_rce_env_var}" ]; then rtl_lconcat \$_rce_env_vars_except "${_rce_env_var}"; fi; done; rtl_lfilter2 \$_rce_env_vars \$_rce_env_vars_unset "${_rce_env_vars_except}"; rtl_unset_vars ${_rce_env_vars_unset}; return 0; }; # # rtl_get_cpu_count() - obtain CPU count # @_rstatus: out reference to status string # @_rcount: out reference to CPU count # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_get_cpu_count() { local _rgcc_rstatus="${1#\$}" _rgcc_rcount="${2#\$}" \ _rgcc_line="" _rgcc_ncpus=0 _rgcc_rc=0 _rgcc_sname=""; _rgcc_sname="$(uname -s 2>/dev/null)" || return 1; case "${_rgcc_sname}" in Linux) if [ ! -e "/proc/cpuinfo" ]; then _rgcc_rc=1; rtl_setrstatus "${_rgcc_rstatus}" 'Error: /proc/cpuinfo non-existent.'; else while read -r _rgcc_line; do if rtl_match "${_rgcc_line}" "processor*:"; then : $((_rgcc_ncpus+=1)); fi; done < /proc/cpuinfo; _rgcc_rc=0; rtl_setrstatus "${_rgcc_rstatus}" ""; fi; ;; *) _rgcc_rc=1; rtl_setrstatus "${_rgcc_rstatus}" 'Error: unknown platform \`'"${_rgcc_sname}"''\''.'; ;; esac; eval ${_rgcc_rcount}='${_rgcc_ncpus}'; return "${_rgcc_rc}"; }; # # rtl_get_var_unsafe() - get value of variable # @_rvval: out reference to variable value # @[-u]: optionally convert variable name to upper case # @_vname: variable name # # Returns: zero (0) on success, non-zero (>0) on failure # N.B.: This function is *unsafe* and impossible to implement otherwise w/o filtering @_vname # and implicitly allows for code execution and other undefined behaviour via @_vname. # Do *not* pass untrusted input through @_vname. # rtl_get_var_unsafe() { local _rgvu_rvval="${1#\$}" \ _rgvu_vname=""; shift; if [ "x${1}" = "x-u" ]; then shift; _rgvu_vname="${1}"; rtl_toupper \$_rgvu_vname; else _rgvu_vname="${1}"; fi; eval ${_rgvu_rvval}="\${${_rgvu_vname}:-}"; return 0; }; # # rtl_kill_tree() - kill tree of processes # @_rpids: inout reference to list of PIDs # @_pid: top-level PID # @_signal: signal(7) to kill with # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_kill_tree() { local _rkt_rpids="${1#\$}" _rkt_pid="${2}" _rkt_signal="${3:-TERM}" \ _rkt_pid_child="" _rkt_pids=""; if _rkt_pids="$(pgrep -P "${_rkt_pid}")"\ && [ "${_rkt_pids:+1}" = 1 ]; then for _rkt_pid_child in ${_rkt_pids}; do rtl_kill_tree "${_rkt_rpids}" "${_rkt_pid_child}" "${_rkt_signal}"; done; fi; if [ "${_rkt_pid:-0}" -ne "${$}" ]\ && kill "-${_rkt_signal}" "${_rkt_pid}" 2>/dev/null; then rtl_lconcat "${_rkt_rpids}" "${_rkt_pid}"; fi; return 0; }; # # rtl_run_cmdlineV() - run command line w/ field splitting applied # @_sep: single non-zero, possibly multi-character, separator # @_cmd: command name # @...: command arguments as positional parameters # # Returns: zero (0) on success, non-zero (>0) on failure # N.B.: This is required in situations where any of the command arguments 1) are passed from # and as a single, expanded parameter (e.g. "${MAKEFLAGS:-}") 2) the value of the parameter # contains multiple parameters separated by @_sep that must be passed as separate arguments # to @_cmd. # rtl_run_cmdlineV() { local _rrc_sep="${1}" _rrc_cmd="${2}" \ _rrc_cmdline="" _rrc_rc="" IFS; shift 2; while [ ${#} -gt 0 ]; do [ "${1:+1}" = 1 ] &&\ _rrc_cmdline="${_rrc_cmdline:+${_rrc_cmdline}${_rrc_sep}}${1}"; shift; done; IFS="${_rrc_sep}"; ${_rrc_cmd} ${_rrc_cmdline}; _rrc_rc=$?; return ${_rrc_rc}; }; # # rtl_set_var_from_spec() - set variable from name-value specification # @_rstatus: out reference to status string # @_arg: variable name-value specification separated by single "=" (e.g. name=value) # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_set_var_from_spec() { local _rsvfs_rstatus="${1#\$}" _rsvfs_arg="${2}" \ _rsvfs_rc=0 _rsvfs_vname="" _rsvfs_vval=""; _rsvfs_vname="${_rsvfs_arg%%=*}"; _rsvfs_vval="${_rsvfs_arg#*=}"; if [ "${_rsvfs_vval:+1}" != 1 ]; then _rsvfs_rc=1; rtl_setrstatus "${_rsvfs_rstatus}" 'empty value specified for \${'"${_rsvfs_vname}"'}.'; else rtl_set_var_unsafe "${_rsvfs_vname}" "${_rsvfs_vval}"; fi; return "${_rsvfs_rc}"; }; # # rtl_set_var() - set variable from variables w/ template # @_vars_set_vname: list of variable names # @_vname_dst: variable name to set # @_vname_src_tmpls: variable name template (e.g. "DEFAULT PKG_") # # Returns: zero (0) on success, non-zero (>0) on failure # rtl_set_var() { local _rsv_vars_set_vname="${1}" _rsv_vname_dst="${2}" _rsv_vname_src_tmpls="${3}" \ _rsv_vars_set_old="" _rsv_vars_set_tmp="" _rsv_vname_src="" _rsv_vnames_src=""; rtl_toupper2 \$_rsv_vname_src_tmpls \$_rsv_vnames_src; for _rsv_vname_src in ${_rsv_vnames_src}; do _rsv_vname_src="${_rsv_vname_src}_${_rsv_vname_dst}"; eval _rsv_vval_src="\${${_rsv_vname_src}:-}"; if [ "${_rsv_vval_src:+1}" = 1 ]; then eval PKG_${_rsv_vname_dst}='${_rsv_vval_src}'; _rsv_vars_set_tmp="${_rsv_vars_set_tmp:+${_rsv_vars_set_tmp} }PKG_${_rsv_vname_dst}"; fi; done; eval _rsv_vars_set_old="\${${_rsv_vars_set_vname}}"; rtl_set_var_unsafe "${_rsv_vars_set_vname}" "${_rsv_vars_set_old:+${_rsv_vars_set_old} }${_rsv_vars_set_tmp}"; return 0; }; # # rtl_set_var_unsafe() - set value of variable # @[-u]: optionally convert variable name to upper case # @_vname: variable name # @_vval: variable value # # Returns: zero (0) on success, non-zero (>0) on failure # N.B.: This function is *unsafe* and impossible to implement otherwise w/o filtering @_vname # and implicitly allows for code execution and other undefined behaviour via @_vname. # Do *not* pass untrusted input through @_vname. # rtl_set_var_unsafe() { local _rsvu_vname="" _rsvu_vval=""; if [ "x${1}" = "x-u" ]; then shift; _rsvu_vname="${1}"; _rsvu_vval="${2}"; rtl_toupper \$_rsvu_vname; else _rsvu_vname="${1}"; _rsvu_vval="${2}"; fi; eval ${_rsvu_vname}='${_rsvu_vval}'; return 0; }; # vim:filetype=sh textwidth=0