# #
###############################################################################
+# A simple print statement
+function print() {
+ local fmt=${1}; shift
+
+ printf -- "${fmt}\n" "$@"
+}
+
+# The args() function takes a number of arguments like
+# var1="abc d" var2="abc" var3="abcd e"
+# and splits them into several arguments, devided by newline
+function args() {
+ echo "$@" | xargs printf "%s\n"
+}
+
+function unquote() {
+ local var="$@"
+
+ if [ "${var:0:1}" = "\"" ]; then
+ var=${var:1}
+ fi
+
+ local last=$(( ${#var} - 1 ))
+ if [ ${last} -ge 0 ] && [ "${var:${last}:1}" = "\"" ]; then
+ var=${var:0:${last}}
+ fi
+
+ print "${var}"
+}
+
+function quote() {
+ print "\"%s\"" "$@"
+}
+
+function strip() {
+ local value="$@"
+
+ # remove leading whitespace characters
+ value="${value#"${value%%[![:space:]]*}"}"
+
+ # remove trailing whitespace characters
+ value="${value%"${value##*[![:space:]]}"}"
+
+ print "${value}"
+}
+
# Print a pretty error message
function error() {
- echo -e " ${FAIL}ERROR${NORMAL} : $@" >&2
+ echo -e " ${CLR_RED_B}ERROR${CLR_RESET} : $@" >&2
}
function error_log() {
- error "$@"
log ERROR "$@"
}
# Print a pretty warn message
function warning() {
- echo -e " ${WARN}WARNING${NORMAL}: $@" >&2
+ echo -e " ${CLR_YELLOW_B}WARNING${CLR_RESET}: $@" >&2
}
function warning_log() {
- warning "$@"
log WARNING "$@"
}
+# The next three functions are kept for backwards
+# compatibility. The need to be dropped at some time.
function listsort() {
- local i
- for i in $@; do
- echo "${i}"
- done | sort | tr "\n" " "
+ list_sort $@
}
-function config_read() {
- local config_file=${1}
+function listmatch() {
+ list_match $@
+}
- if [ -e "${config_file}" ]; then
- . ${config_file}
- config_check
- fi
+function listlength() {
+ list_length $@
}
-function config_write() {
- local config_file=${1}
- shift
+# Speedup function to avoid a call of the basename binary
+function basename() {
+ echo "${1##*/}"
+}
- # Check if all values to be written are sane
- config_check
+function format() {
+ local key=${1}
+ assert isset key
- log DEBUG "Writing configuration file ${config_file}."
+ local format=${2}
+ assert isset format
- > ${config_file}
+ shift 2
- local param
- for param in $(listsort $@); do
- echo "${param}=\"${!param}\"" >> ${config_file}
- done
+ printf -v "${key}" "${format}" "$@"
}
-function config_print() {
- local param
-
- for param in $(listsort $@); do
- printf "%-16s = %s\n" "${param}" "${!param}"
- done
-}
+function assign() {
+ local key=${1}
+ assert isset key
+ shift
-function config_check() {
- # If there is a function defined that is called __check
- # we call that function
- [ -n "$(type -t _check)" ] && _check
+ format "${key}" "%s" "$@"
}
-function network_config_set() {
- while [ $# -gt 0 ]; do
- case "${1}" in
- *=*)
- log INFO "Setting configuration option '${1}'".
- eval ${1}
- ;;
- *)
- warning "Invalid parameter given: ${1}"
- ;;
- esac
- shift
- done
-
- # Write configuration to disk
- network_config_write
-}
+function fread() {
+ local file=${1}
+ assert isset file
-function network_config_read() {
- config_read ${CONFIG_FILE}
-}
+ [ -r "${file}" ] || return ${EXIT_ERROR}
-function network_config_write() {
- config_write ${CONFIG_FILE} ${CONFIG_FILE_PARAMS}
+ print "$(<${file})"
}
-function network_config_print() {
- config_print ${CONFIG_FILE_PARAMS}
-}
+function fwrite() {
+ local file=${1}
+ assert isset file
+ shift
-# Speedup function to avoid a call of the basename binary
-function basename() {
- echo "${1##*/}"
+ print "%s" "$@" >> ${file}
}
function enabled() {
local param=${1}
- [ "${!param}" = "yes" ] || [ "${!param}" = "on" ] || [ "${!param}" = "1" ]
+ list_match "${!param}" yes on true 1
}
function mac_generate() {
- local mac=()
+ # Get a bunch of random hex digits
+ # and remove all dashes from the input.
+ local random=$(</proc/sys/kernel/random/uuid)
+ random=${random//-/}
+ assert isset random
+
+ local output
+
+ local i o
for i in $(seq 0 5); do
- mac[i]="0x$(uuid | cut -c 1-2)"
- done
+ o="0x${random:0:2}"
+ random="${random:2:${#random}}"
- # Remove multicast bit
- # and set address is software assigned
- # XXX must doublecheck if this works
- mac[0]=$((mac[0] & 0xfe))
- mac[0]=$((mac[0] | 0x02))
+ case "${i}" in
+ 0)
+ # Remove multicast bit
+ # and set address is software assigned
+ o=$(( ${o} & 0xfe ))
+ o=$(( ${o} | 0x02 ))
- local output
- for i in ${mac[*]}; do
- if [ -n "${output}" ]; then
- output="${output}:"
- fi
-
- output="${output}$(printf "%02x" ${i})"
+ printf -v output "%02x" "${o}"
+ ;;
+ *)
+ printf -v output "%s:%02x" "${output}" "${o}"
+ ;;
+ esac
done
# Check if output is valid
assert mac_is_valid ${output}
- echo ${output}
+ echo "${output}"
+}
+
+function mac_format() {
+ local mac=${1}
+ assert isset mac
+
+ # Remove all colons and make the rest lowercase.
+ mac=${mac//:/}
+ mac=${mac,,}
+
+ local output
+ if [ "${#mac}" = "12" ]; then
+ # Add colons (:) to mac address
+ output=${mac:0:2}
+ local i
+ for i in 2 4 6 8 10; do
+ output="${output}:${mac:${i}:2}"
+ done
+ else
+ output=${mac}
+ fi
+
+ assert mac_is_valid ${output}
+
+ print "${output}"
}
function mac_is_valid() {
}
function uuid() {
- cat /proc/sys/kernel/random/uuid
+ echo $(</proc/sys/kernel/random/uuid)
}
function isset() {
local var=${!1}
shift
- for i in $@; do
- [ "${var}" = "${i}" ] && return ${EXIT_OK}
- done
-
- return ${EXIT_ERROR}
+ list_match "${var}" "$@"
}
function isbool() {
mac_is_valid ${mac}
}
+function isipaddress() {
+ local addr=${!1}
+
+ ip_is_valid ${addr}
+}
+
+function backtrace() {
+ local start=1
+
+ echo # Empty line
+ error_log "Backtrace (most recent call in first line):"
+
+ local i source
+ for i in $(seq ${start} ${#BASH_SOURCE[*]}); do
+ [ -z "${FUNCNAME[${i}]}" ] && continue
+ [ "${FUNCNAME[${i}]}" == "main" ] && continue
+
+ source=${BASH_SOURCE[$(( ${i} + 1 ))]}
+ error_log " $(printf "%20s" "'${FUNCNAME[${i}]}'") called from ${source:-<shell>}:${BASH_LINENO[${i}]}"
+ done
+}
+
function assert() {
local assertion="$@"
if ! ${assertion}; then
- error "Assertion '${assertion}' failed."
- exit ${EXIT_ERROR}
+ error_log "Assertion '${assertion}' failed."
+ backtrace
+ exit ${EXIT_ERROR_ASSERT}
fi
return ${EXIT_OK}
}
+
+# This function checks, if the given argument is an assert error
+# exit code. If this is the case, the script will halt immediately.
+function assert_check_retval() {
+ local ret=${1}
+
+ if [ ${ret} -eq ${EXIT_ERROR_ASSERT} ]; then
+ exit ${EXIT_ERROR_ASSERT}
+ fi
+
+ return ${ret}
+}
+
+function exec_cmd() {
+ local cmd=$@
+
+ log DEBUG "Running command: ${cmd}"
+
+ DEBUG=${DEBUG} \
+ LOG_DISABLE_STDOUT="${LOG_DISABLE_STDOUT}" \
+ LOG_FACILITY="${LOG_FACILITY}" \
+ ${SHELL} ${cmd}
+ local ret=$?
+
+ #log DEBUG "Returned with code '${ret}'"
+
+ if [ ${ret} -eq ${EXIT_ERROR_ASSERT} ]; then
+ error_log "Stopping parent process due to assertion error in child process: ${cmd}"
+ exit ${EXIT_ERROR_ASSERT}
+ fi
+
+ return ${ret}
+}
+
+function cmd() {
+ local cmd=$@
+
+ log DEBUG "Running command: ${cmd}"
+
+ ${cmd}
+ local ret=$?
+
+ log DEBUG "Returned with code '${ret}'"
+
+ return ${ret}
+}
+
+function cmd_quiet() {
+ cmd $@ &>/dev/null
+}
+
+function cmd_exec() {
+ local cmd=$@
+
+ log DEBUG "Exec'ing command: ${cmd}"
+
+ exec ${cmd}
+
+ log ERROR "Could not exec-ute: ${cmd}"
+ exit ${EXIT_ERROR}
+}
+
+function seq() {
+ if [ $# -eq 2 ]; then
+ eval echo {${1}..${2}}
+ elif [ $# -eq 3 ]; then
+ eval echo {${1}..${3}..${2}}
+ fi
+}
+
+function which() {
+ type -P $@
+}
+
+# Prints the number of seconds since epoch.
+function timestamp() {
+ date -u "+%s"
+}
+
+function beautify_time() {
+ local value=${1}
+
+ local unit
+ local limit
+ for unit in s m h d w; do
+ case "${unit}" in
+ s|m|h)
+ limit=60
+ ;;
+ d)
+ limit=24
+ ;;
+ w)
+ limit=7
+ ;;
+ esac
+
+ [ ${value} -lt ${limit} ] && break
+
+ value=$(( ${value} / ${limit} ))
+ done
+
+ echo "${value}${unit}"
+}
+
+function beautify_bytes() {
+ local value=${1}
+
+ local unit
+ local limit=1024
+ for unit in B k M G T; do
+ [ ${value} -lt ${limit} ] && break
+ value=$(( ${value} / ${limit} ))
+ done
+
+ echo "${value}${unit}"
+}
+
+function module_load() {
+ local module=${1}
+
+ if ! grep -q "^${module}" /proc/modules; then
+ log DEBUG "Loading module '${module}'."
+ modprobe ${module}
+ fi
+}
+
+function binary_exists() {
+ local binary=${1}
+
+ if [ -n "$(type -p ${binary})" ]; then
+ return ${EXIT_OK}
+ fi
+
+ return ${EXIT_ERROR}
+}
+
+function process_kill() {
+ local process=${1}
+
+ if ! isinteger process; then
+ process=$(pidof ${process})
+ fi
+
+ local pid
+ local sig
+ for pid in ${process}; do
+ for sig in 15 9; do
+ [ -d "/proc/${pid}" ] || break
+
+ kill -${sig} ${pid}
+ sleep 1
+ done
+ done
+}
+
+function dec() {
+ local hex=${1}
+
+ if [ "${hex:0:2}" != "0x" ]; then
+ hex="0x${hex}"
+ fi
+
+ printf "%d\n" "${hex}"
+}
+
+function network_is_running() {
+ # Check, if the network service is running.
+ service_is_active network
+}
+
+function contains_spaces() {
+ local var="$@"
+
+ # Eliminate spaces.
+ local var2=${var// /}
+
+ if [ ${#var} -ne ${#var2} ]; then
+ return ${EXIT_TRUE}
+ fi
+
+ return ${EXIT_FALSE}
+}