###############################################################################
# A simple print statement
-function print() {
+print() {
local fmt=${1}; shift
printf -- "${fmt}\n" "$@"
}
+print_indent() {
+ local i=${1}
+ shift
+
+ while (( i-- )); do
+ printf "\t"
+ done
+
+ print "%s" "$@"
+}
+
# 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() {
+args() {
echo "$@" | xargs printf "%s\n"
}
-function unquote() {
+unquote() {
local var="$@"
if [ "${var:0:1}" = "\"" ]; then
print "${var}"
}
-function quote() {
+quote() {
print "\"%s\"" "$@"
}
-function strip() {
+strip() {
local value="$@"
# remove leading whitespace characters
}
# Print a pretty error message
-function error() {
+error() {
echo -e " ${CLR_RED_B}ERROR${CLR_RESET} : $@" >&2
}
-function error_log() {
+error_log() {
log ERROR "$@"
}
# Print a pretty warn message
-function warning() {
+warning() {
echo -e " ${CLR_YELLOW_B}WARNING${CLR_RESET}: $@" >&2
}
-function warning_log() {
+warning_log() {
log WARNING "$@"
}
-# The next three functions are kept for backwards
-# compatibility. The need to be dropped at some time.
-function listsort() {
- list_sort $@
-}
-
-function listmatch() {
- list_match $@
-}
-
-function listlength() {
- list_length $@
-}
-
# Speedup function to avoid a call of the basename binary
-function basename() {
+basename() {
echo "${1##*/}"
}
-function format() {
+format() {
local key=${1}
assert isset key
printf -v "${key}" "${format}" "$@"
}
-function assign() {
+format_time() {
+ local s=${1}
+ local ret m
+
+ local units="s m h"
+
+ local unit
+ for unit in ${units}; do
+ m=$(( ${s} % 60 ))
+ s=$(( ${s} / 60 ))
+
+ if [ ${m} -gt 0 ]; then
+ ret="${m}${unit} ${ret}"
+ fi
+ done
+
+ # Remove whitespace
+ echo ${ret}
+}
+
+parse_time() {
+ local ret=0
+
+ local arg
+ for arg in "$@"; do
+ local unit
+
+ case "${arg}" in
+ *h|*m|*s)
+ # Store unit
+ unit="${arg: -1}"
+
+ # Remove unit
+ arg="${arg:0:-1}"
+ ;;
+ esac
+
+ if ! isinteger arg; then
+ return ${EXIT_ERROR}
+ fi
+
+ # Convert hours and minutes into seconds
+ case "${unit}" in
+ h)
+ arg=$(( ${arg} * 3600 ))
+ ;;
+ m)
+ arg=$(( ${arg} * 60 ))
+ ;;
+ esac
+
+ # Add up everything
+ ret=$(( ${ret} + ${arg} ))
+ done
+
+ print "${ret}"
+}
+
+assign() {
local key=${1}
assert isset key
shift
format "${key}" "%s" "$@"
}
-function fread() {
+fread() {
local file=${1}
assert isset file
print "$(<${file})"
}
-function fwrite() {
+fwrite() {
local file=${1}
assert isset file
shift
- if [ ! -w "${file}" ]; then
+ if ! print "%s" "$@" > ${file} 2>/dev/null; then
+ error "Could not write to file: ${file}"
+ return ${EXIT_ERROR}
+ fi
+
+ return ${EXIT_OK}
+}
+
+fappend() {
+ local file=${1}
+ assert isset file
+ shift
+
+ if [ -e "${file}" ] && [ ! -w "${file}" ]; then
log ERROR "${file}: No such file"
return ${EXIT_ERROR}
fi
print "%s" "$@" >> ${file} 2>/dev/null
}
-function enabled() {
+file_delete() {
+ local file=${1}
+
+ unlink "${file}" 2>/dev/null
+}
+
+file_exists() {
+ local file=${1}
+
+ [ -e "${file}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
+}
+
+file_is_newer_than() {
+ local file1="${1}"
+ local file2="${2}"
+
+ local age1=$(file_get_age "${file1}")
+ local age2=$(file_get_age "${file2}")
+
+ if [ ${age1} -gt ${age2} ]; then
+ return ${EXIT_TRUE}
+ else
+ return ${EXIT_FALSE}
+ fi
+}
+
+file_get_age() {
+ local file="${1}"
+
+ if [ -e "${file}" ]; then
+ stat --format="%Y" "${file}"
+ return $?
+ fi
+
+ return ${EXIT_ERROR}
+}
+
+make_directory() {
+ local path="${1}"
+
+ # Exit silently when directory already exists
+ if [ -d "${path}" ]; then
+ return ${EXIT_OK}
+ fi
+
+ if ! mkdir -p "${path}"; then
+ log ERROR "Could not create directory ${path}"
+ return ${EXIT_ERROR}
+ fi
+
+ log DEBUG "Created directory ${path}"
+ return ${EXIT_OK}
+}
+
+make_parent_directory() {
+ local path="${1}"
+
+ make_directory "$(dirname "${path}")"
+}
+
+enabled() {
local param=${1}
list_match "${!param}" yes on true 1
}
-function mac_generate() {
- # 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
+disabled() {
+ local param="${1}"
- local output
+ list_match "${!param}" no off false 0
+}
- local i o
- for i in $(seq 0 5); do
- o="0x${random:0:2}"
- random="${random:2:${#random}}"
+mac_generate() {
+ local b="$(random 12)"
- case "${i}" in
- 0)
- # Remove multicast bit
- # and set address is software assigned
- o=$(( ${o} & 0xfe ))
- o=$(( ${o} | 0x02 ))
+ # Remove multicast bit
+ # and set address is software assigned
+ local first_byte=$(( 0x${b:0:2} & 0xfe ))
+ first_byte=$(( ${first_byte} | 0x02 ))
- printf -v output "%02x" "${o}"
- ;;
- *)
- printf -v output "%s:%02x" "${output}" "${o}"
- ;;
- esac
- done
+ local output
+ printf -v output "%02x" "${first_byte}"
+
+ output="${output}:${b:2:2}:${b:4:2}:${b:6:2}:${b:8:2}:${b:10:2}"
# Check if output is valid
- assert mac_is_valid ${output}
+ assert mac_is_valid "${output}"
echo "${output}"
}
-function mac_format() {
+mac_format() {
local mac=${1}
assert isset mac
print "${output}"
}
-function mac_is_valid() {
+mac_is_valid() {
local mac=${1}
[[ ${mac} =~ ^([0-9a-f]{2}\:){5}[0-9a-f]{2}$ ]]
}
-function uuid() {
+# Converts the given string to lowercase and returns true if it is a valid FQDN
+fqdn_is_valid() {
+ local fqdn="${1}"
+
+ if grep -qP "^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$" <<< "${fqdn,,}"; then
+ return ${EXIT_TRUE}
+ fi
+
+ return ${EXIT_FALSE}
+}
+
+uuid() {
echo $(</proc/sys/kernel/random/uuid)
}
-function isset() {
+abs() {
+ local val=${1}
+
+ if [ ${val} -lt 0 ]; then
+ (( val *= -1 ))
+ fi
+
+ echo ${val}
+}
+
+rand() {
+ local uuid="$(uuid)"
+ echo "${uuid//-/}"
+}
+
+random() {
+ local length="${1:-8}"
+
+ local random
+ while [ ${#random} -lt ${length} ]; do
+ random="${random}$(rand)"
+ done
+
+ echo "${random:0:${length}}"
+}
+
+isset() {
local var=${1}
[ -n "${!var}" ]
}
-function isoneof() {
+isoneof() {
local var=${!1}
shift
list_match "${var}" "$@"
}
-function isbool() {
+isbool() {
local var=${1}
- isoneof ${var} 0 1 no yes on off
+ isoneof ${var} 0 1 no yes on off true false
}
-function isinteger() {
+isinteger() {
local var=${!1}
[[ ${var} =~ ^[0-9]+$ ]]
}
-function ismac() {
+ismac() {
local mac=${!1}
mac_is_valid ${mac}
}
-function isipaddress() {
+isipaddress() {
local addr=${!1}
ip_is_valid ${addr}
}
-function backtrace() {
+mtu_is_valid() {
+ local proto=${1}
+ local mtu=${2}
+
+ case ${proto} in
+ ethernet|ipv4)
+ [ ${mtu} -ge 576 ] && [ ${mtu} -le 9000 ]
+ ;;
+ ipv6)
+ [ ${mtu} -ge 1280 ] && [ ${mtu} -le 9000 ]
+ ;;
+ *)
+ error "${proto} is not a valid proto"
+ return ${EXIT_ERROR}
+ ;;
+ esac
+}
+
+backtrace() {
local start=1
echo # Empty line
done
}
-function assert() {
+assert() {
local assertion="$@"
if ! ${assertion}; then
# 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() {
+assert_check_retval() {
local ret=${1}
if [ ${ret} -eq ${EXIT_ERROR_ASSERT} ]; then
return ${ret}
}
-function exec_cmd() {
+# This function executes the given command and inverses the return code
+not() {
+ local command="$@"
+
+ ${command} && return ${EXIT_FALSE} || return ${EXIT_TRUE}
+}
+
+exec_cmd() {
local cmd=$@
log DEBUG "Running command: ${cmd}"
return ${ret}
}
-function cmd() {
+cmd() {
local cmd=$@
log DEBUG "Running command: ${cmd}"
- ${cmd}
+ env -i -- \
+ HOME="${HOME}" \
+ PATH="${PATH}" \
+ TERM="${TERM}" \
+ ${cmd}
local ret=$?
- log DEBUG "Returned with code '${ret}'"
-
- return ${ret}
+ case "${ret}" in
+ ${EXIT_OK})
+ return ${EXIT_OK}
+ ;;
+ *)
+ log DEBUG "Returned with code '${ret}'"
+ return ${ret}
+ ;;
+ esac
}
-function cmd_quiet() {
- cmd $@ &>/dev/null
+cmd_quiet() {
+ cmd "$@" &>/dev/null
}
-function cmd_exec() {
+cmd_exec() {
local cmd=$@
log DEBUG "Exec'ing command: ${cmd}"
exit ${EXIT_ERROR}
}
-function cmd_not_implemented() {
+cmd_not_implemented() {
assert false "not implemented"
}
-function seq() {
+# Executes the given command in background
+cmd_background() {
+ cmd_quiet "$@" &
+}
+
+# Prints the PID of the process that was started last
+cmd_background_get_pid() {
+ print "${!}"
+}
+
+cmd_background_result() {
+ local pids=$@
+
+ wait ${pids}
+}
+
+# Increase security of the read command
+read() {
+ builtin read -r "$@"
+}
+
+seq() {
if [ $# -eq 2 ]; then
eval echo {${1}..${2}}
elif [ $# -eq 3 ]; then
fi
}
-function which() {
- type -P $@
+range() {
+ eval echo {0..$(( ${1} - 1 ))}
+}
+
+count() {
+ local i=0
+
+ while read; do
+ ((i++))
+ done
+
+ echo ${i}
+}
+
+which() {
+ type -P "$@"
}
# Prints the number of seconds since epoch.
-function timestamp() {
+timestamp() {
date -u "+%s"
}
-function beautify_time() {
+beautify_time() {
local value=${1}
local unit
echo "${value}${unit}"
}
-function beautify_bytes() {
+beautify_bytes() {
local value=${1}
local unit
echo "${value}${unit}"
}
-function module_load() {
+module_load() {
local module=${1}
- if ! grep -q "^${module}" /proc/modules; then
- log DEBUG "Loading module '${module}'."
- modprobe ${module}
+ # Do nothing if the module is already loaded
+ if [ -d "/sys/module/${module//-/_}" ]; then
+ return ${EXIT_OK}
fi
+
+ log DEBUG "Loading kernel module ${module}"
+ modprobe "${module}"
}
-function binary_exists() {
+binary_exists() {
local binary=${1}
if [ -n "$(type -p ${binary})" ]; then
return ${EXIT_ERROR}
}
-function process_kill() {
+function_exists() {
+ local function="${1}"
+
+ if [ "$(type -t "${function}")" = "function" ]; then
+ return ${EXIT_TRUE}
+ fi
+
+ return ${EXIT_FALSE}
+}
+
+process_kill() {
local process=${1}
if ! isinteger process; then
done
}
-function dec() {
+dec() {
local hex=${1}
if [ "${hex:0:2}" != "0x" ]; then
printf "%d\n" "${hex}"
}
-function chr() {
+chr() {
local char="${1}"
[ ${char} -lt 256 ] || return ${EXIT_ERROR}
printf "\\$(( ${char} / 64 * 100 + ${char} % 64 / 8 * 10 + ${char} % 8 ))\n"
}
-function ord() {
+ord() {
LC_CTYPE="C" printf "%d\n" "'${1}"
}
-function hex() {
+hex() {
printf "%X\n" "${1}"
}
-function network_is_running() {
+network_is_running() {
# Check, if the network service is running.
service_is_active network
}
-function contains_spaces() {
+contains_spaces() {
local var="$@"
# Eliminate spaces.
return ${EXIT_FALSE}
}
-function string_split() {
+string_match() {
+ local match=${1}
+ local string=${2}
+
+ [[ ${string} =~ ${match} ]] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
+}
+
+string_split() {
local string="$@"
local pos=0
return ${EXIT_OK}
}
-function string_reverse() {
+string_reverse() {
local string="$@"
local output
return ${EXIT_OK}
}
-function dec2bin() {
+dec2bin() {
local number="${1}"
local output
print "${output}"
}
-function bin2dec() {
+bin2dec() {
local string="${1}"
local number=0
return ${EXIT_OK}
}
-function char2bin() {
+char2bin() {
local dec="$(ord "${1}")"
dec2bin "${dec}"
}
-function bin2char() {
+bin2char() {
local dec="$(bin2dec "$@")"
chr "${dec}"
}
-function bin2hex() {
+bin2hex() {
local dec="$(bin2dec "$@")"
dec2hex "${dec}"
}
-function hex2bin() {
+hex2bin() {
local dec="$(hex2dec "$@")"
dec2bin "${dec}"
}
-function hex2dec() {
+hex2dec() {
local hex="${1}"
# Prepend 0x if necessary.
printf "%d\n" "${hex}"
}
-function dec2hex() {
+dec2hex() {
printf "%02x\n" "${1}"
}
+
+# This function just copy config files
+copy() {
+ assert [ $# -eq 2 ]
+
+ local src=${1}
+ local dst=${2}
+
+ # Check if we can read from the source
+ if [ ! -r "${src}" ]; then
+ log ERROR "Cannot read ${src}"
+ return ${EXIT_ERROR}
+ fi
+
+ # Check if ${dst} is a directory
+ if [ -d "${dst}" ]; then
+ log ERROR "${dst} is a directory"
+ return ${EXIT_ERROR}
+ fi
+
+ # Create destination directory if it doesn't exist, yet
+ if ! make_parent_directory "${dst}"; then
+ return ${EXIT_ERROR}
+ fi
+
+ if ! fread "${src}" > "${dst}"; then
+ log ERROR "Could not copy data from ${src} to ${dst}"
+ return ${EXIT_ERROR}
+ fi
+}
+
+normalize() {
+ local string="$@"
+
+ tr -sc [:alnum:] "-" < <(printf "%s" "${string,,}")
+}
+
+get_driver_from_path() {
+ local path="${1}"
+
+ if file_exists "${path}"; then
+ # Resolve symlink
+ local driver="$(readlink "${path}")"
+
+ # Print module name
+ basename "${driver}"
+ return ${EXIT_OK}
+ fi
+
+ return ${EXIT_ERROR}
+}