3 # Copyright (c) 2012 Ron McDowell
4 # Copyright (c) 2012-2013 Devin Teske
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
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.
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
30 ############################################################ INCLUDES
32 BSDCFG_SHARE="/usr/share/bsdconfig"
33 . $BSDCFG_SHARE/common.subr || exit 1
34 f_dprintf "%s: loading includes..." "$0"
35 f_include $BSDCFG_SHARE/dialog.subr
36 f_include $BSDCFG_SHARE/mustberoot.subr
37 f_include $BSDCFG_SHARE/strings.subr
39 BSDCFG_LIBE="/usr/libexec/bsdconfig"
40 f_include_lang $BSDCFG_LIBE/include/messages.subr
42 BSDCONFIG_HELPFILE=$BSDCFG_LIBE/include/bsdconfig.hlp
43 USAGE_HELPFILE=$BSDCFG_LIBE/include/usage.hlp
45 ############################################################ FUNCTIONS
49 # display usage and exit
53 local index="INDEX" cmd_list=""
56 # No need to preserve CWD (headed toward exit)
58 # Test for language-specific indices
59 f_quietly ls */"$index.${LANG:-$LC_ALL}" &&
60 index="$index.${LANG:-$LC_ALL}"
63 awk '/^menu_selection="/ {
65 sub(/^menu_selection="/, "")
71 # Determine the longest command-length (in characters)
74 longest_cmd=$( echo "$cmd_list" | f_longest_line_length )
75 f_dprintf "longest_cmd=[%s]" "$longest_cmd"
78 # Determine the maximum width of terminal/console
80 local max_size max_width
81 max_size=$( stty size 2> /dev/null )
82 : ${max_size:="24 80"}
83 max_width="${max_size#*[$IFS]}"
84 f_dprintf "max_width=[%s]" "$max_width"
87 # Using the longest command-length as the width of a single column,
88 # determine if we can use more than one column to display commands.
90 local x=$longest_cmd ncols=1
91 x=$(( $x + 8 )) # Accomodate leading tab character
92 x=$(( $x + 3 + $longest_cmd )) # Preload end of next column
93 while [ $x -lt $max_width ]; do
94 ncols=$(( $ncols + 1 ))
95 x=$(( $x + 3 + $longest_cmd ))
97 f_dprintf "ncols=[%u] x=[%u]" $ncols $x
100 # Re-format the command-list into multiple columns
102 cmd_list=$( eval "$( echo "$cmd_list" |
103 awk -v ncols=$ncols -v size=$longest_cmd '
110 fmt = "printf \"\\t%-" size "s"
111 for (i = 1; i < cur_col; i++)
112 fmt = fmt " %-" size "s"
115 for (i = 1; i <= cur_col; i++)
116 printf " \"%s\"", row_item[i]
121 cur_col = (( n - 1 ) % ncols ) + 1
122 printf "f_dprintf \"row_item[%u]=[%%s]\" \"%s\"\n",
124 row_item[cur_col] = $0
125 if ( cur_col == ncols ) print_row()
128 if ( cur_col < ncols ) print_row()
132 f_usage $BSDCFG_LIBE/USAGE \
133 "PROGRAM_NAME" "$pgm" \
134 "COMMAND_LIST" "$cmd_list"
141 # Display the dialog(1)-based application main menu.
145 local title="$DIALOG_TITLE"
146 local btitle="$DIALOG_BACKTITLE"
147 local prompt="$msg_menu_text"
151 'X' '$msg_exit' '$msg_exit_bsdconfig'
152 '1' '$msg_usage' '$msg_quick_start_how_to_use_this_menu_system'
155 local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }"
157 local menuitem menu_title menu_help menu_selection index=2
158 for menuitem in $( cd $BSDCFG_LIBE && ls -d [0-9][0-9][0-9].* ); do
159 [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
160 tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
165 f_include_lang $BSDCFG_LIBE/$menuitem/INDEX
166 [ "$menu_program" ] || continue
168 case "$menu_program" in
169 /*) : already fully qualified ;;
171 menu_program="$menuitem/$menu_program"
174 menu_title=$( echo "$menu_title" | awk "$sanitize_awk" )
175 menu_help=$( echo "$menu_help" | awk "$sanitize_awk" )
176 setvar "menu_program$tag" "$menu_program"
177 menu_list="$menu_list '$tag' '$menu_title' '$menu_help'"
179 index=$(( $index + 1 ))
182 size=$( eval f_dialog_menu_with_help_size \
190 dialog_menu=$( eval $DIALOG \
192 --title \"\$title\" \
193 --backtitle \"\$btitle\" \
195 --ok-label \"\$msg_ok\" \
196 --cancel-label \"\$msg_exit_bsdconfig\" \
198 --help-label \"\$msg_help\" \
199 ${USE_XDIALOG:+--help \"\"} \
200 --default-item \"\$DEFAULTITEM_$$\" \
201 --menu \"\$prompt\" $size $menu_list \
202 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
205 setvar DIALOG_MENU_$$ "$dialog_menu"
207 # Only update default-item on success
208 [ $retval -eq 0 ] && setvar DEFAULTITEM_$$ "$dialog_menu"
213 ############################################################ MAIN
216 # If $0 is not "bsdconfig", interpret it either as a keyword to a menuitem or
217 # as a valid resword (see script.subr for additional details about reswords).
219 if [ "$pgm" != "bsdconfig" ]; then
220 if indexfile=$( f_index_file "$pgm" ) &&
221 cmd=$( f_index_menusel_command "$indexfile" "$pgm" )
223 f_dprintf "pgm=[%s] indexfile=[%s] cmd=[%s]" \
224 "$pgm" "$indexfile" "$cmd"
225 exec "$cmd" "$@" || exit 1
227 f_include $BSDCFG_SHARE/script.subr
228 for resword in $RESWORDS; do
229 [ "$pgm" = "$resword" ] || continue
231 f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
239 # Process command-line arguments
242 while getopts dD:f:hSX flag; do
244 f) [ $scripts_loaded -eq 0 ] && f_include $BSDCFG_SHARE/script.subr
245 f_script_load "$OPTARG"
246 scripts_loaded=$(( $scripts_loaded + 1 ));;
250 shift $(( $OPTIND -1 ))
252 # If we've loaded any scripts, do not continue any further
253 [ $scripts_loaded -gt 0 ] && exit
258 f_dialog_title "$msg_main_menu"
260 [ "$SECURE" ] && f_mustberoot_init
262 # Incorporate rc-file if it exists
263 [ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
266 # If a non-option argument was passed, process it as a menuitem selection...
270 # ...unless it's a long-option for usage.
273 -help|--help|-\?) usage;;
277 # Find the INDEX (possibly i18n) claiming this keyword and get the
278 # command to execute from the menu_selection line.
280 if ! { indexfile=$( f_index_file "$1" ) &&
281 cmd=$( f_index_menusel_command "$indexfile" "$1" )
283 # no matches, display usage (which shows valid keywords)
284 f_err "%s: %s: $msg_not_found\n" "$pgm" "$1"
289 exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
293 # Launch application main menu
298 mtag=$( f_dialog_menutag )
299 f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
301 if [ $retval -eq 2 ]; then
302 # The Help button was pressed
303 f_show_help "$BSDCONFIG_HELPFILE"
305 elif [ $retval -ne 0 ]; then
315 f_show_help "$USAGE_HELPFILE"
319 *) # Dynamically loaded menuitem
320 f_getvar menu_program$mtag menu_program
321 case "$menu_program" in
322 /*) cmd="$menu_program";;
323 *) cmd="$BSDCFG_LIBE/$menu_program"
325 f_dprintf "cmd=[%s]" "$cmd"
326 $cmd ${USE_XDIALOG:+-X}
333 ################################################################################
335 ################################################################################