]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bsdconfig/bsdconfig
Make the internal assertion correct--only fail when '\0' is found in
[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 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
38
39 BSDCFG_LIBE="/usr/libexec/bsdconfig"
40 f_include_lang $BSDCFG_LIBE/include/messages.subr
41
42 BSDCONFIG_HELPFILE=$BSDCFG_LIBE/include/bsdconfig.hlp
43 USAGE_HELPFILE=$BSDCFG_LIBE/include/usage.hlp
44
45 ############################################################ FUNCTIONS
46
47 # usage
48 #
49 # display usage and exit
50 #
51 usage()
52 {
53         local index="INDEX" cmd_list=""
54
55         cd $BSDCFG_LIBE
56                 # No need to preserve CWD (headed toward exit)
57
58         # Test for language-specific indices
59         f_quietly ls */"$index.${LANG:-$LC_ALL}" &&
60                 index="$index.${LANG:-$LC_ALL}"
61
62         cmd_list=$(
63                 awk '/^menu_selection="/ {
64                         sub(/\|.*/, "")
65                         sub(/^menu_selection="/, "")
66                         print
67                 }' */$index | sort
68         )
69
70         #
71         # Determine the longest command-length (in characters)
72         #
73         local longest_cmd
74         longest_cmd=$( echo "$cmd_list" | f_longest_line_length )
75         f_dprintf "longest_cmd=[%s]" "$longest_cmd"
76
77         #
78         # Determine the maximum width of terminal/console
79         #
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"
85
86         #
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.
89         #
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 ))
96         done
97         f_dprintf "ncols=[%u] x=[%u]" $ncols $x
98
99         #
100         # Re-format the command-list into multiple columns
101         #
102         cmd_list=$( eval "$( echo "$cmd_list" |
103                 awk -v ncols=$ncols -v size=$longest_cmd '
104                 BEGIN {
105                         n = 0
106                         row_item[1] = ""
107                 }
108                 function print_row()
109                 {
110                         fmt = "printf \"\\t%-" size "s"
111                         for (i = 1; i < cur_col; i++)
112                                 fmt = fmt "   %-" size "s"
113                         fmt = fmt "\\n\""
114                         printf "%s", fmt
115                         for (i = 1; i <= cur_col; i++)
116                                 printf " \"%s\"", row_item[i]
117                         print ""
118                 }
119                 {
120                         n++
121                         cur_col = (( n - 1 ) % ncols ) + 1
122                         printf "f_dprintf \"row_item[%u]=[%%s]\" \"%s\"\n",
123                                cur_col, $0
124                         row_item[cur_col] = $0
125                         if ( cur_col == ncols ) print_row()
126                 }
127                 END {
128                         if ( cur_col < ncols ) print_row()
129                 }' )"
130         )
131
132         f_usage $BSDCFG_LIBE/USAGE \
133                 "PROGRAM_NAME" "$pgm" \
134                 "COMMAND_LIST" "$cmd_list"
135
136         # Never reached
137 }
138
139 # dialog_menu_main
140 #
141 # Display the dialog(1)-based application main menu.
142 #
143 dialog_menu_main()
144 {
145         local title="$DIALOG_TITLE"
146         local btitle="$DIALOG_BACKTITLE"
147         local prompt="$msg_menu_text"
148         local menu_list size
149
150         menu_list="
151                 'X' '$msg_exit'  '$msg_exit_bsdconfig'
152                 '1' '$msg_usage' '$msg_quick_start_how_to_use_this_menu_system'
153         " # END-QUOTE
154
155         local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }"
156
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 )
161
162                 menu_program=
163                 menu_title=
164                 menu_help=
165                 f_include_lang $BSDCFG_LIBE/$menuitem/INDEX
166                 [ "$menu_program" ] || continue
167
168                 case "$menu_program" in
169                 /*) : already fully qualified ;;
170                 *)
171                         menu_program="$menuitem/$menu_program"
172                 esac
173
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'"
178
179                 index=$(( $index + 1 ))
180         done
181
182         size=$( eval f_dialog_menu_with_help_size \
183                         \"\$title\"  \
184                         \"\$btitle\" \
185                         \"\$prompt\" \
186                         \"\"         \
187                         $menu_list   )
188
189         local dialog_menu
190         dialog_menu=$( eval $DIALOG \
191                 --clear                                 \
192                 --title \"\$title\"                     \
193                 --backtitle \"\$btitle\"                \
194                 --item-help                             \
195                 --ok-label \"\$msg_ok\"                 \
196                 --cancel-label \"\$msg_exit_bsdconfig\" \
197                 --help-button                           \
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
203         )
204         local retval=$?
205         setvar DIALOG_MENU_$$ "$dialog_menu"
206
207         # Only update default-item on success
208         [ $retval -eq 0 ] && setvar DEFAULTITEM_$$ "$dialog_menu"
209
210         return $retval
211 }
212
213 ############################################################ MAIN
214
215 #
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).
218 #
219 if [ "$pgm" != "bsdconfig" ]; then
220         if indexfile=$( f_index_file "$pgm" ) &&
221            cmd=$( f_index_menusel_command "$indexfile" "$pgm" )
222         then
223                 f_dprintf "pgm=[%s] indexfile=[%s] cmd=[%s]" \
224                           "$pgm" "$indexfile" "$cmd"
225                 exec "$cmd" "$@" || exit 1
226         else
227                 f_include $BSDCFG_SHARE/script.subr
228                 for resword in $RESWORDS; do
229                         [ "$pgm" = "$resword" ] || continue
230                         # Found a match
231                         f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
232                         f_dispatch $resword
233                         exit $?
234                 done
235         fi
236 fi
237
238 #
239 # Process command-line arguments
240 #
241 scripts_loaded=0
242 while getopts dD:f:hSX flag; do
243         case "$flag" in
244         f) [ $scripts_loaded -eq 0 ] && f_include $BSDCFG_SHARE/script.subr
245            f_script_load "$OPTARG"
246            scripts_loaded=$(( $scripts_loaded + 1 ));;
247         h|\?) usage;;
248         esac
249 done
250 shift $(( $OPTIND -1 ))
251
252 # If we've loaded any scripts, do not continue any further
253 [ $scripts_loaded -gt 0 ] && exit
254
255 #
256 # Initialize
257 #
258 f_dialog_title "$msg_main_menu"
259
260 [ "$SECURE" ] && f_mustberoot_init
261
262 # Incorporate rc-file if it exists
263 [ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
264
265 #
266 # If a non-option argument was passed, process it as a menuitem selection...
267 #
268 if [ "$1" ]; then
269         #
270         # ...unless it's a long-option for usage.
271         #
272         case "$1" in
273         -help|--help|-\?) usage;;
274         esac
275
276         #
277         # Find the INDEX (possibly i18n) claiming this keyword and get the
278         # command to execute from the menu_selection line.
279         #
280         if ! { indexfile=$( f_index_file "$1" ) &&
281                cmd=$( f_index_menusel_command "$indexfile" "$1" )
282         }; then
283                 # no matches, display usage (which shows valid keywords)
284                 f_err "%s: %s: $msg_not_found\n" "$pgm" "$1"
285                 usage
286         fi
287
288         shift
289         exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
290 fi
291
292 #
293 # Launch application main menu
294 #
295 while :; do
296         dialog_menu_main
297         retval=$?
298         mtag=$( f_dialog_menutag )
299         f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
300
301         if [ $retval -eq 2 ]; then
302                 # The Help button was pressed
303                 f_show_help "$BSDCONFIG_HELPFILE"
304                 continue
305         elif [ $retval -ne 0 ]; then
306                 f_die
307         fi
308
309         case "$mtag" in
310         X) # Exit
311            break
312            ;;
313
314         1) # Usage
315            f_show_help "$USAGE_HELPFILE"
316            continue
317            ;;
318
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"
324            esac
325            f_dprintf "cmd=[%s]" "$cmd"
326            $cmd ${USE_XDIALOG:+-X}
327
328         esac
329 done
330
331 exit $SUCCESS
332
333 ################################################################################
334 # END
335 ################################################################################