1if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 2# 3# Copyright (c) 2012 Ron McDowell 4# Copyright (c) 2012 Devin Teske 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28# $FreeBSD$ 29# 30############################################################ GLOBALS 31 32# 33# Program name 34# 35pgm="${0##*/}" 36 37# 38# Program arguments 39# 40ARGC="$#" 41ARGV="$@" 42 43# 44# Global exit status variables 45# 46SUCCESS=0 47FAILURE=1 48 49############################################################ FUNCTIONS 50 51# 52# This is an empty function by default, to use it, copy 53# /usr/share/examples/bsdconfig/bsdconfigrc to $HOME/.bsdconfigrc 54# 55f_dprintf() 56{ 57 : this page intentionally left blank 58} 59 60# f_err $fmt [ $opts ... ] 61# 62# Print a message to stderr (fd=2). 63# 64f_err() 65{ 66 printf "$@" >&2 67} 68 69# f_quietly $command [ $arguments ... ] 70# 71# Run a command quietly (quell any output to stdout or stderr) 72# 73f_quietly() 74{ 75 "$@" > /dev/null 2>&1 76} 77 78# f_have $anything ... 79# 80# A wrapper to the `type' built-in. Returns true if argument is a valid shell 81# built-in, keyword, or externally-tracked binary, otherwise false. 82# 83f_have() 84{ 85 f_quietly type "$@" 86} 87 88# f_die [ $status [ $fmt [ $opts ... ]]] 89# 90# Abruptly terminate due to an error optionally displaying a message in a 91# dialog box using printf(1) syntax. 92# 93f_die() 94{ 95 local status=$FAILURE 96 97 # If there is at least one argument, take it as the status 98 if [ $# -gt 0 ]; then 99 status=$1 100 shift 1 # status 101 fi 102 103 # If there are still arguments left, pass them to f_show_msg 104 [ $# -gt 0 ] && f_show_msg "$@" 105 106 # Optionally call f_clean_up() function if it exists 107 f_have f_clean_up && f_clean_up 108 109 exit $status 110} 111 112# f_interrupt 113# 114# Interrupt handler. 115# 116f_interrupt() 117{ 118 exec 2>&1 # fix sh(1) bug where stderr gets lost within async-trap 119 f_die 120} 121 122# f_show_msg $fmt [ $opts ... ] 123# 124# Display a message in a dialog box using printf(1) syntax. 125# 126f_show_msg() 127{ 128 local msg 129 msg=$( printf "$@" ) 130 131 # 132 # Use f_dialog_msgbox from dialog.subr if possible, otherwise fall 133 # back to dialog(1) (without options, making it obvious when using 134 # un-aided system dialog). 135 # 136 if f_have f_dialog_msgbox; then 137 f_dialog_msgbox "$msg" 138 else 139 dialog --msgbox "$msg" 0 0 140 fi 141} 142 143# f_include $file 144# 145# Include a shell subroutine file. 146# 147# If the subroutine file exists but returns error status during loading, exit 148# is called and execution is prematurely terminated with the same error status. 149# 150f_include() 151{ 152 local file="$1" 153 . "$file" || exit $? 154} 155 156# f_include_lang $file 157# 158# Include a language file. Automatically takes $LANG and $LC_ALL into 159# consideration when including $file (suffix ".$LC_ALL" or ".$LANG" will 160# automatically by added prior to loading the language file). 161# 162# No error is produced if (a) a language has been requested (by setting either 163# $LANG or $LC_ALL in the environment) and (b) the language file does not 164# exist -- in which case we will fall back to loading $file without-suffix. 165# 166# If the language file exists but returns error status during loading, exit 167# is called and execution is prematurely terminated with the same error status. 168# 169f_include_lang() 170{ 171 local file="$1" 172 local lang="${LANG:-$LC_ALL}" 173 174 f_dprintf "lang=[$lang]" 175 if [ -f "$file.$lang" ]; then 176 . "$file.$lang" || exit $? 177 else 178 . "$file" || exit $? 179 fi 180} 181 182# f_usage $file [ $key1 $value1 ... ] 183# 184# Display USAGE file with optional pre-processor macro definitions. The first 185# argument is the template file containing the usage text to be displayed. If 186# $LANG or $LC_ALL (in order of preference, respectively) is set, ".encoding" 187# will automatically be appended as a suffix to the provided $file pathname. 188# 189# When processing $file, output begins at the first line containing that is 190# (a) not a comment, (b) not empty, and (c) is not pure-whitespace. All lines 191# appearing after this first-line are output, including (a) comments (b) empty 192# lines, and (c) lines that are purely whitespace-only. 193# 194# If additional arguments appear after $file, substitutions are made while 195# printing the contents of the USAGE file. The pre-processor macro syntax is in 196# the style of autoconf(1), for example: 197# 198# f_usage $file "FOO" "BAR" 199# 200# Will cause instances of "@FOO@" appearing in $file to be replaced with the 201# text "BAR" before bering printed to the screen. 202# 203# This function is a two-parter. Below is the awk(1) portion of the function, 204# afterward is the sh(1) function which utilizes the below awk script. 205# 206f_usage_awk=' 207BEGIN { found = 0 } 208{ 209 if ( !found && $0 ~ /^[[:space:]]*($|#)/ ) next 210 found = 1 211 print 212} 213' 214f_usage() 215{ 216 local file="$1" 217 local lang="${LANG:-$LC_ALL}" 218 219 f_dprintf "lang=[$lang]" 220 221 shift 1 # file 222 223 local usage 224 if [ -f "$file.$lang" ]; then 225 usage=$( awk "$f_usage_awk" "$file.$lang" ) || exit $FAILURE 226 else 227 usage=$( awk "$f_usage_awk" "$file" ) || exit $FAILURE 228 fi 229 230 while [ $# -gt 0 ]; do 231 local key="$1" 232 export value="$2" 233 usage=$( echo "$usage" | awk \ 234 "{ gsub(/@$key@/, ENVIRON[\"value\"]); print }" ) 235 shift 2 236 done 237 238 f_err "%s\n" "$usage" 239 240 exit $FAILURE 241} 242 243# f_index_menu_selection $file $pgm 244# 245# Process $file looking for $menu_selection values that correspond to $pgm. 246# This function is for internationalization (i18n) mapping of the on-disk 247# scriptname ($pgm) into the localized language (given language-specific 248# $file). If $LANG or $LC_ALL (in orderder of preference, respectively) is set, 249# ".encoding" will automatically be appended as a suffix to the provided $file 250# pathname. 251# 252# If, within $file, multiple $menu_selection values map to $pgm, only the first 253# one will be returned. If no mapping can be made, the NULL string is returned. 254# 255# If $file does not exist, error status is returned along with the NULL string. 256# 257# This function is a two-parter. Below is the awk(1) portion of the function, 258# afterward is the sh(1) function which utilizes the below awk script. 259# 260f_index_menusel_awk=' 261# Variables that should be defined on the invocation line: 262# -v pgm="program_name" 263# 264( $0 ~ "^menu_selection=.*\\|" pgm "\"" ) { 265 sub(/\|.*/, "") 266 sub(/^menu_selection="/, "") 267 print 268 exit 269} 270' 271f_index_menu_selection() 272{ 273 local file="$1" pgm="$2" 274 local lang="${LANG:-$LC_ALL}" 275 276 f_dprintf "lang=[$lang]" 277 278 if [ -f "$file.$lang" ]; then 279 awk -v pgm="$pgm" "$f_index_menusel_awk" "$file.$lang" || 280 exit $FAILURE 281 elif [ -f "$file" ]; then 282 awk -v pgm="$pgm" "$f_index_menusel_awk" "$file" || 283 exit $FAILURE 284 else 285 return $FAILURE 286 fi 287} 288 289############################################################ MAIN 290 291# 292# Trap signals so we can recover gracefully 293# 294trap 'f_interrupt' SIGINT 295trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \ 296 SIGFPE SIGTRAP SIGABRT SIGSEGV 297trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM 298 299fi # ! $_COMMON_SUBR 300