]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bsdconfig/bsdconfig
Import driver source from hyperv-20130627 vendor branch.
[FreeBSD/FreeBSD.git] / usr.sbin / bsdconfig / bsdconfig
1 #!/bin/sh
2 #-
3 # Copyright (c) 2012 Ron McDowell
4 # Copyright (c) 2012-2013 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 ############################################################ INCLUDES
31
32 # When common.subr is included, it automatically scans "$@" for `-d' and/or
33 # `-D file' arguments to conditionally enable debugging. Similarly, when
34 # dialog.subr is included, it automatically scans "$@" for `-X' and/or `-S'.
35 # To prevent this scanning from becoming confused by extra options, define
36 # any/all extra arguments to use in the optstring to getopts when scanning
37 # for dedicated options such as those described.
38 #
39 # NOTE: This needs to be declared before including `common.subr'.
40 # NOTE: You really only need to list flags that require an argument as unknown
41 #       flags are silently accepted unless they take an argument (in which case
42 #       the following argument will terminate option processing unless it looks
43 #       like a flag).
44 #
45 GETOPTS_EXTRA="f:"
46
47 BSDCFG_SHARE="/usr/share/bsdconfig"
48 . $BSDCFG_SHARE/common.subr || exit 1
49 f_dprintf "%s: loading includes..." "$0"
50 f_include $BSDCFG_SHARE/dialog.subr
51 f_include $BSDCFG_SHARE/mustberoot.subr
52 f_include $BSDCFG_SHARE/strings.subr
53
54 BSDCFG_LIBE="/usr/libexec/bsdconfig"
55 f_include_lang $BSDCFG_LIBE/include/messages.subr
56
57 BSDCONFIG_HELPFILE=$BSDCFG_LIBE/include/bsdconfig.hlp
58 USAGE_HELPFILE=$BSDCFG_LIBE/include/usage.hlp
59
60 ############################################################ FUNCTIONS
61
62 # usage
63 #
64 # display usage and exit
65 #
66 usage()
67 {
68         local index="INDEX"
69         local cmd_list # Calculated below
70
71         cd $BSDCFG_LIBE
72                 # No need to preserve CWD (headed toward exit)
73
74         # Test for language-specific indices
75         f_quietly ls */"$index.${LANG:-$LC_ALL}" &&
76                 index="$index.${LANG:-$LC_ALL}"
77
78         cmd_list=$(
79                 awk '/^menu_selection="/ {
80                         sub(/\|.*/, "")
81                         sub(/^menu_selection="/, "")
82                         print
83                 }' */$index | sort
84         )
85
86         #
87         # Determine the longest command-length (in characters)
88         #
89         local longest_cmd
90         longest_cmd=$( echo "$cmd_list" | f_longest_line_length )
91         f_dprintf "longest_cmd=[%s]" "$longest_cmd"
92
93         #
94         # Determine the maximum width of terminal/console
95         #
96         local max_size="$( stty size 2> /dev/null )"
97         : ${max_size:="24 80"}
98         local max_width="${max_size#*[$IFS]}"
99         f_dprintf "max_width=[%s]" "$max_width"
100
101         #
102         # Using the longest command-length as the width of a single column,
103         # determine if we can use more than one column to display commands.
104         #
105         local x=$longest_cmd ncols=1
106         x=$(( $x + 8 )) # Accomodate leading tab character
107         x=$(( $x + 3 + $longest_cmd )) # Preload end of next column
108         while [ $x -lt $max_width ]; do
109                 ncols=$(( $ncols + 1 ))
110                 x=$(( $x + 3 + $longest_cmd ))
111         done
112         f_dprintf "ncols=[%u] x=[%u]" $ncols $x
113
114         #
115         # Re-format the command-list into multiple columns
116         #
117         cmd_list=$( eval "$( echo "$cmd_list" |
118                 awk -v ncols=$ncols -v size=$longest_cmd '
119                 BEGIN {
120                         n = 0
121                         row_item[1] = ""
122                 }
123                 function print_row()
124                 {
125                         fmt = "printf \"\\t%-" size "s"
126                         for (i = 1; i < cur_col; i++)
127                                 fmt = fmt "   %-" size "s"
128                         fmt = fmt "\\n\""
129                         printf "%s", fmt
130                         for (i = 1; i <= cur_col; i++)
131                                 printf " \"%s\"", row_item[i]
132                         print ""
133                 }
134                 {
135                         n++
136                         cur_col = (( n - 1 ) % ncols ) + 1
137                         printf "f_dprintf \"row_item[%u]=[%%s]\" \"%s\"\n",
138                                cur_col, $0
139                         row_item[cur_col] = $0
140                         if ( cur_col == ncols ) print_row()
141                 }
142                 END {
143                         if ( cur_col < ncols ) print_row()
144                 }' )"
145         )
146
147         f_usage $BSDCFG_LIBE/USAGE \
148                 "PROGRAM_NAME" "$pgm" \
149                 "COMMAND_LIST" "$cmd_list"
150
151         # Never reached
152 }
153
154 # dialog_menu_main
155 #
156 # Display the dialog(1)-based application main menu.
157 #
158 dialog_menu_main()
159 {
160         local title="$DIALOG_TITLE"
161         local btitle="$DIALOG_BACKTITLE"
162         local prompt="$msg_menu_text"
163         local menu_list="
164                 'X' '$msg_exit'  '$msg_exit_bsdconfig'
165                 '1' '$msg_usage' '$msg_quick_start_how_to_use_this_menu_system'
166         " # END-QUOTE
167         local defaultitem= # Calculated below
168         local hline=
169
170         local menuitem menu_title menu_help menu_selection index=2
171         for menuitem in $( cd $BSDCFG_LIBE && ls -d [0-9][0-9][0-9].* ); do
172                 [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
173                 tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
174
175                 menu_program=
176                 menu_title=
177                 menu_help=
178                 f_include_lang $BSDCFG_LIBE/$menuitem/INDEX
179                 [ "$menu_program" ] || continue
180
181                 case "$menu_program" in
182                 /*) : already fully qualified ;;
183                  *) menu_program="$menuitem/$menu_program"
184                 esac
185
186                 f_shell_escape "$menu_title" menu_title
187                 f_shell_escape "$menu_help" menu_help
188                 setvar "menu_program$tag" "$menu_program"
189                 menu_list="$menu_list '$tag' '$menu_title' '$menu_help'"
190
191                 index=$(( $index + 1 ))
192         done
193
194         local height width rows
195         eval f_dialog_menu_with_help_size height width rows \
196                                           \"\$title\"  \
197                                           \"\$btitle\" \
198                                           \"\$prompt\" \
199                                           \"\$hline\"  \
200                                           $menu_list
201
202         # Obtain default-item from previously stored selection
203         f_dialog_default_fetch defaultitem
204
205         local menu_choice
206         menu_choice=$( eval $DIALOG \
207                 --clear                                 \
208                 --title \"\$title\"                     \
209                 --backtitle \"\$btitle\"                \
210                 --hline \"\$hline\"                     \
211                 --item-help                             \
212                 --ok-label \"\$msg_ok\"                 \
213                 --cancel-label \"\$msg_exit_bsdconfig\" \
214                 --help-button                           \
215                 --help-label \"\$msg_help\"             \
216                 ${USE_XDIALOG:+--help \"\"}             \
217                 --default-item \"\$defaultitem\"        \
218                 --menu \"\$prompt\"                     \
219                 $height $width $rows                    \
220                 $menu_list                              \
221                 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
222         )
223         local retval=$?
224         f_dialog_data_sanitize menu_choice
225         f_dialog_menutag_store "$menu_choice"
226
227         # Only update default-item on success
228         [ $retval -eq 0 ] && f_dialog_default_store "$menu_choice"
229
230         return $retval
231 }
232
233 ############################################################ MAIN
234
235 #
236 # If $0 is not "bsdconfig", interpret it either as a keyword to a menuitem or
237 # as a valid resword (see script.subr for additional details about reswords).
238 #
239 if [ "$pgm" != "bsdconfig" ]; then
240         if indexfile=$( f_index_file "$pgm" ) &&
241            cmd=$( f_index_menusel_command "$indexfile" "$pgm" )
242         then
243                 f_dprintf "pgm=[%s] indexfile=[%s] cmd=[%s]" \
244                           "$pgm" "$indexfile" "$cmd"
245                 exec "$cmd" "$@" || exit 1
246         else
247                 f_include $BSDCFG_SHARE/script.subr
248                 for resword in $RESWORDS; do
249                         [ "$pgm" = "$resword" ] || continue
250                         # Found a match
251                         f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
252                         f_dispatch $resword
253                         exit $?
254                 done
255         fi
256 fi
257
258 #
259 # Process command-line arguments
260 #
261 scripts_loaded=0
262 while getopts f:h$GETOPTS_STDARGS flag; do
263         case "$flag" in
264         f) [ $scripts_loaded -eq 0 ] && f_include $BSDCFG_SHARE/script.subr
265            f_script_load "$OPTARG"
266            scripts_loaded=$(( $scripts_loaded + 1 )) ;;
267         h|\?) usage ;;
268         esac
269 done
270 shift $(( $OPTIND -1 ))
271
272 # If we've loaded any scripts, do not continue any further
273 [ $scripts_loaded -gt 0 ] && exit
274
275 #
276 # Initialize
277 #
278 f_dialog_title "$msg_main_menu"
279
280 [ "$SECURE" ] && f_mustberoot_init
281
282 # Incorporate rc-file if it exists
283 [ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
284
285 #
286 # If a non-option argument was passed, process it as a menuitem selection...
287 #
288 if [ "$1" ]; then
289         #
290         # ...unless it's a long-option for usage.
291         #
292         case "$1" in -help|--help|-\?)
293                 usage
294                 # Not reached
295         esac
296
297         #
298         # Find the INDEX (possibly i18n) claiming this keyword and get the
299         # command to execute from the menu_selection line.
300         #
301         if ! { indexfile=$( f_index_file "$1" ) &&
302                cmd=$( f_index_menusel_command "$indexfile" "$1" )
303         }; then
304                 # no matches, display usage (which shows valid keywords)
305                 f_err "%s: %s: $msg_not_found\n" "$pgm" "$1"
306                 usage
307                 # Not reached
308         fi
309
310         shift
311         exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
312         # Not reached
313 fi
314
315 #
316 # Launch application main menu
317 #
318 while :; do
319         dialog_menu_main
320         retval=$?
321         f_dialog_menutag_fetch mtag
322         f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
323
324         if [ $retval -eq 2 ]; then
325                 # The Help button was pressed
326                 f_show_help "$BSDCONFIG_HELPFILE"
327                 continue
328         elif [ $retval -ne 0 ]; then
329                 f_die
330         fi
331
332         case "$mtag" in
333         X) break ;;
334         1) # Usage
335            f_show_help "$USAGE_HELPFILE"
336            continue
337         esac
338
339         # Anything else is a dynamically loaded menuitem
340
341         f_getvar menu_program$mtag menu_program
342         case "$menu_program" in
343         /*) cmd="$menu_program" ;;
344          *) cmd="$BSDCFG_LIBE/$menu_program"
345         esac
346         f_dprintf "cmd=[%s]" "$cmd"
347         $cmd ${USE_XDIALOG:+-X}
348 done
349
350 exit $SUCCESS
351
352 ################################################################################
353 # END
354 ################################################################################