# bl-include.cfg - Variables and functions commonly used in custom scripts
# for Bunsen Labs Linux.
# Originally for CrunchBang GNU/Linux .
# Can be used in user scripts too, by first including this file, eg:
# BL_COMMON_LIBDIR='/usr/lib/bunsen/bunsen-common'
# if ! . "$BL_COMMON_LIBDIR/bl-include.cfg" 2> /dev/null; then
# echo $"Error: Failed to locate bl-include.cfg in $BL_COMMON_LIBDIR" >&2
# exit 1
# fi
########################################################################
# Functions to generate Openbox menus.
menuStart() {
echo ' '
}
# Usage: menuItem label command
menuItem() {
echo " - "
echo ' '
echo ' '
echo " $(XMLescape "$2")"
echo ' '
echo ' '
echo '
'
}
# Usage: menuSeparator [label]
menuSeparator() {
if [[ $1 ]]; then
echo " "
else
echo ' '
fi
}
# Usage menuSubmenu id label # http://openbox.org/wiki/Help:Menus
menuSubmenu() {
echo " '
}
menuEnd() {
echo ' '
}
# escape special characters
XMLescape() {
local string="${1//&/&}"
string="${string//<}"
string="${string//>/>}"
string="${string//\"/"}"
string="${string//\'/'}"
printf '%s' "$string"
}
OBlabelEscape() {
printf '%s' "${1//_/__}"
}
########################################################################
# rerun script in terminal if necessary
# Usage: terminalCheck [ -T title ] [arguments...]
terminalCheck() {
if ! [[ -t 0 && -t 1 && -t 2 ]]; then # not attached to terminal
if [[ -n $DISPLAY ]]; then # running X
if [[ $1 = '-T' ]];then
local title=$2
shift 2
exec x-terminal-emulator -T "$title" -e "$0" "$@"
else
exec x-terminal-emulator -e "$0" "$@"
fi
else
echo "$0: no terminal" >&2
exit 1
fi
fi
}
# Usage: createFlag filename
createFlag() {
mkdir -p "$HOME/.config/bunsen"
touch "$HOME/.config/bunsen/$1"
}
# Check the connection by downloading a file from ftp.debian.org. No disk space used.
# Usage: connectiontest [attempts]
# If attempt count is not specified or 0, then it will loop forever and exit(!) your main program with 1 exit status.
connectiontest() {
local TEXT_CHECKING='Checking internet connection...'
local TEXT_FAILED='Internet connection test failed!'
local TEXT_ASK_RETRY=$'\n\nThis script requires a working internet connection. Please configure your internet connection, then hit "Enter" to continue, else hit "q" to quit.'
local TEXT_ABORT='Script aborted.'
local TEXT_OK='Internet connection test passed!'
local -i i attempts=${1-0}
for (( i=0; i < attempts || attempts == 0; i++ )); do
say "$TEXT_CHECKING"
if wget -O - 'http://ftp.debian.org/debian/README' &> /dev/null; then
say "$TEXT_OK" 1
return 0
fi
say "$TEXT_FAILED"
if (( i == attempts - 1 )); then # if last attempt
return 1
elif prompt "$TEXT_ASK_RETRY" Q; then # if user wants to quit
say "$TEXT_ABORT" 2
(( attempts == 0 )) && exit 1 || return 1
fi
tput clear
done
}
########################################################################
# User interface functions.
# Usage: say text [delayAfterText|pause]
say() {
fold -s -w 76 <<< "$1" | sed 's/^/ /' # wraps text nicely and adds two leading spaces
if [[ $2 = 'pause' ]]
then
echo 'Press any key to continue.'
read -srn1
else
sleep "${2:-0}"
fi
}
# Usage errorExit message [details]
errorExit() {
say $'\n'"$1"$'\n' '1' >&2
[[ $2 ]] && {
while true
do
local REPLY
read -rn1 -p ' Press "d" for details (q to quit) '
[[ ${REPLY^} = Q ]] && exit 1
[[ ${REPLY^} = D ]] && {
echo $'\n\n'
tput setaf 1
echo "$2" >&2
tput sgr0
say "
Would you like to quit now, or continue anyway?
(Be careful!)
Press \"q\" to quit, \"c\" to continue:
"
read -r
[[ ${REPLY^} = Q ]] && exit 1
[[ ${REPLY^} = C ]] && return 0
}
done
}
say 'Press any key to exit.'
read -srn1
exit 1
}
# Usage: prompt text [ Y | N | Q | ]
prompt() {
local answer prompt default
if [[ ${2^} = Q ]]; then
while true; do
read -srn1 -p "$1" answer
echo
[[ ${answer^} = Q ]] && return 0
[[ ! $answer ]] && return 1
done
fi
if [[ ! $2 || ${2^} = Y ]]; then
prompt='Y/n'
default='Y'
elif [[ ${2^} = N ]]; then
prompt='y/N'
default='N'
else
prompt=
default=
fi
while true; do
read -r -p "$1 ${prompt:+[$prompt] }" answer
if [[ ! $prompt && ! $default ]]; then
if [[ $answer = $2 ]]; then
echo
return 0
elif [[ ${answer^} = Q ]]; then
echo
return 1
else
continue
fi
fi
[[ ! $answer ]] &&
answer=$default
if [[ ${answer^} = Y || ${answer^^} = YES ]]; then
echo
return 0
elif [[ ${answer^} = N || ${answer^^} = NO ]]; then
echo
return 1
fi
done
}
# Usage: promptInstall [--apt-get-option] name description package [package...]
# Use: promptInstall [--apt-get-option] --setup functionname name desc...
# to have functionname run first
promptInstall() {
local arg=
if [[ $1 = -* && $1 != --setup ]]; then
arg=$1
shift
fi
local setupFunction=
if [[ $1 = '--setup' ]]; then
if [[ -n $2 && $(type -t "$2") = 'function' ]]; then
setupFunction="$2"
shift 2
else
say "Error: $2 is not a function."
return 1
fi
fi
tput clear
local title="INSTALL ${1^^}"
say "
$title
${title//?/-}
$2
"
prompt ' Run the installer now?' || return 0
tput clear
connectiontest || return 1
if [[ -n $setupFunction ]]; then
"$setupFunction" || return 1 # run setup function if it exists
fi
tput clear
say 'Updating sources...' 1
safeUpdate || say 'Continuing in spite of update problems...' 3
tput clear
say 'Installing package...' 1
safeInstall $arg "${@:3}" || return 1
tput clear
say "
$1 has been installed successfully.
Hit any key to exit..."
read -srn1
return 0
}
########################################################################
# Apt-get functions.
# apt-get update, exit if error message.
# safeUpdate --ignore 'string' to ignore certain error message
safeUpdate() {
local ignore_string=
[[ $1 = '--ignore' ]] && {
ignore_string="$2"
}
local apt_error
if apt_error=$(LC_MESSAGES=C sudo apt-get update 2>&1 >/dev/tty) && ! grep -iqEv "(${ignore_string:-$^}|^$)" <<<"$apt_error"
then
say 'Finished update'
return 0
else
errorExit 'There were problems during the update.' "$apt_error"
return 1
fi
}
# apt-get upgrade, exit if error message.
# safeUpgrade --dist-upgrade for dist-upgrade
safeUpgrade() {
local cmd='upgrade'
[[ $1 = '--dist-upgrade' ]] && {
cmd='dist-upgrade'
}
local ignore_string1='Extracting templates from packages: 100%' # apt sends this to stderr!
local ignore_string2='Retrieving bug reports... Done' # apt-listbugs sends this to stderr!
local ignore_string3='Parsing Found/Fixed information... Done' # apt-listbugs sends this to stderr!
local apt_error
if apt_error=$(LC_MESSAGES=C sudo apt-get $cmd 2>&1 >/dev/tty) && ! grep -iqEv "(${ignore_string1:-$^}|${ignore_string2:-$^}|${ignore_string3:-$^}|^$)" <<<"$apt_error"
then
say 'Finished upgrade.'
return 0
else
errorExit 'There were problems during the upgrade.' "${apt_error:-Upgrade Aborted}"
return 1
fi
}
# Usage safeInstall [--apt-get-option] package [package...]
safeInstall() {
local ignore_string1='Extracting templates from packages: 100%' # apt sends this to stderr!
local ignore_string2='Retrieving bug reports... Done' # apt-listbugs sends this to stderr!
local ignore_string3='Parsing Found/Fixed information... Done' # apt-listbugs sends this to stderr!
local apt_error
if apt_error=$(LC_MESSAGES=C sudo apt-get install "${@}" 2>&1 >/dev/tty) && ! grep -iqEv "(${ignore_string1:-$^}|${ignore_string2:-$^}|${ignore_string3:-$^}|^$)" <<<"$apt_error"
then
say 'Installation finished sucessfully.'
return 0
else
errorExit "There were problems installing ${*}" "${apt_error:-Install Aborted}"
return 1
fi
}
# Usage safeRemove [--apt-get-option] package [package...]
safeRemove() {
local ignore_string1='Extracting templates from packages: 100%' # apt sends this to stderr!
local ignore_string2='Retrieving bug reports... Done' # apt-listbugs sends this to stderr!
local ignore_string3='Parsing Found/Fixed information... Done' # apt-listbugs sends this to stderr!
local apt_error
if apt_error=$(LC_MESSAGES=C sudo apt-get remove "${@}" 2>&1 >/dev/tty) && ! grep -iqEv "(${ignore_string1}|${ignore_string2}|${ignore_string3}|^$)" <<<"$apt_error"
then
say "Successfully removed ${*}"
return 0
else
errorExit "There were problems removing ${*}" "${apt_error:-Install Aborted}"
return 1
fi
}