# 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 " " } menuSubmenuEnd() { echo ' ' } menuEnd() { echo ' ' } # escape special characters XMLescape() { local string="${1//&/&}" 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 }