]> git.ipfire.org Git - people/stevee/network.git/blobdiff - functions.util
wireless: Add function to find DFS channels.
[people/stevee/network.git] / functions.util
index 3023154a8140ce7cebb85de0182df2f746627876..79ec87db7e579fa078f0f37f8443332ee4feec19 100644 (file)
 #                                                                             #
 ###############################################################################
 
+# 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]="$(uuid)"
-               mac[i]="0x${mac[i]:0: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() {
@@ -162,7 +211,7 @@ function mac_is_valid() {
 }
 
 function uuid() {
-       cat /proc/sys/kernel/random/uuid
+       echo $(</proc/sys/kernel/random/uuid)
 }
 
 function isset() {
@@ -175,11 +224,7 @@ function isoneof() {
        local var=${!1}
        shift
 
-       for i in $@; do
-               [ "${var}" = "${i}" ] && return ${EXIT_OK}
-       done
-
-       return ${EXIT_ERROR}
+       list_match "${var}" "$@"
 }
 
 function isbool() {
@@ -200,13 +245,361 @@ function ismac() {
        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
+
+               # Print called binary with arguments.
+               if [ "${FUNCNAME[${i}]}" == "main" ]; then
+                       local args="$(list_reverse ${BASH_ARGV[*]})"
+                       printf -v source "%20s" "$0"
+                       error_log "  ${source} ${args}"
+                       continue
+               fi
+
+               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_log "Assertion '${assertion}' failed."
-               exit ${EXIT_ERROR}
+               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 cmd_not_implemented() {
+       assert false "not implemented"
+}
+
+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 chr() {
+       local char="${1}"
+
+       [ ${char} -lt 256 ] || return ${EXIT_ERROR}
+
+       printf "\\$(( ${char} / 64 * 100 + ${char} % 64 / 8 * 10 + ${char} % 8 ))\n"
+}
+
+function ord() {
+       LC_CTYPE="C" printf "%d\n" "'${1}"
+}
+
+function hex() {
+       printf "%X\n" "${1}"
+}
+
+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}
+}
+
+function string_split() {
+       local string="$@"
+
+       local pos=0
+       while [ ${pos} -lt ${#string} ]; do
+               print "${string:${pos}:1}"
+               pos=$(( ${pos} + 1 ))
+       done
+
+       return ${EXIT_OK}
+}
+
+function string_reverse() {
+       local string="$@"
+
+       local output
+       local pos=0
+       while [ ${pos} -lt ${#string} ]; do
+               output="${string:${pos}:1}${output}"
+               pos=$(( ${pos} + 1 ))
+       done
+
+       print "${output}"
+       return ${EXIT_OK}
+}
+
+function dec2bin() {
+       local number="${1}"
+
+       local output
+
+       local i div
+       for i in 7 6 5 4 3 2 1; do
+               div=$(( 2 ** ${i} ))
+
+               if [ $(( ${number} / ${div} )) -eq 1 ]; then
+                       output="${output}1"
+               else
+                       output="${output}0"
+               fi
+               number="$(( ${number} % ${div} ))"
+       done
+
+       if [ $(( ${number} % 2 )) -eq 1 ]; then
+               output="${output}1"
+       else
+               output="${output}0"
+       fi
+
+       print "${output}"
+}
+
+function bin2dec() {
+       local string="${1}"
+       local number=0
+
+       local pos=0 char
+       while [ ${pos} -lt ${#string} ]; do
+               char="${string:${pos}:1}"
+               pos=$(( ${pos} + 1 ))
+
+               number=$(( ${number} << 1 ))
+
+               case "${char}" in
+                       0) ;;
+                       1)
+                               number=$(( ${number} + 1 ))
+                               ;;
+                       *)
+                               assert false "Invalid character: ${char}"
+                               ;;
+               esac
+       done
+
+       print "${number}"
+       return ${EXIT_OK}
+}
+
+function char2bin() {
+       local dec="$(ord "${1}")"
+
+       dec2bin "${dec}"
+}
+
+function bin2char() {
+       local dec="$(bin2dec "$@")"
+
+       chr "${dec}"
+}
+
+function bin2hex() {
+       local dec="$(bin2dec "$@")"
+
+       dec2hex "${dec}"
+}
+
+function hex2bin() {
+       local dec="$(hex2dec "$@")"
+
+       dec2bin "${dec}"
+}
+
+function hex2dec() {
+       local hex="${1}"
+
+       # Prepend 0x if necessary.
+       [ "${hex:0:2}" = "0x" ] || hex="0x${hex}"
+
+       printf "%d\n" "${hex}"
+}
+
+function dec2hex() {
+       printf "%02x\n" "${1}"
+}