1if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1 2# 3# Copyright (c) 2006-2013 Devin Teske 4# All Rights Reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27# $FreeBSD$ 28# 29############################################################ INCLUDES 30 31BSDCFG_SHARE="/usr/share/bsdconfig" 32. $BSDCFG_SHARE/common.subr || exit 1 33f_dprintf "%s: loading includes..." dialog.subr 34f_include $BSDCFG_SHARE/strings.subr 35f_include $BSDCFG_SHARE/variable.subr 36 37BSDCFG_LIBE="/usr/libexec/bsdconfig" 38f_include_lang $BSDCFG_LIBE/include/messages.subr 39 40############################################################ CONFIGURATION 41 42# 43# Default file descriptor to link to stdout for dialog(1) passthru allowing 44# execution of dialog from within a sub-shell (so-long as its standard output 45# is explicitly redirected to this file descriptor). 46# 47: ${DIALOG_TERMINAL_PASSTHRU_FD:=${TERMINAL_STDOUT_PASSTHRU:-3}} 48 49############################################################ GLOBALS 50 51# 52# Default name of dialog(1) utility 53# NOTE: This is changed to "Xdialog" by the optional `-X' argument 54# 55DIALOG="dialog" 56 57# 58# Default dialog(1) title and backtitle text 59# 60DIALOG_TITLE="$pgm" 61DIALOG_BACKTITLE="bsdconfig" 62 63# 64# Settings used while interacting with dialog(1) 65# 66DIALOG_MENU_TAGS="123456789ABCDEFGHIJKLMNOPQRSTUVWYZabcdefghijklmnopqrstuvwxyz" 67 68# 69# Declare that we are fully-compliant with Xdialog(1) by unset'ing all 70# compatibility settings. 71# 72unset XDIALOG_HIGH_DIALOG_COMPAT 73unset XDIALOG_FORCE_AUTOSIZE 74unset XDIALOG_INFOBOX_TIMEOUT 75 76# 77# Default behavior is to call f_dialog_init() automatically when loaded. 78# 79: ${DIALOG_SELF_INITIALIZE=1} 80 81# 82# Default terminal size (used if/when running without a controlling terminal) 83# 84: ${DEFAULT_TERMINAL_SIZE:=24 80} 85 86############################################################ GENERIC FUNCTIONS 87 88# f_dialog_title [$new_title] 89# 90# Set the title of future dialog(1) ($DIALOG_TITLE) or backtitle of Xdialog(1) 91# ($DIALOG_BACKTITLE) invocations. If no arguments are given or the first 92# argument is NULL, the current title is returned. 93# 94# Each time this function is called, a backup of the current values is made 95# allowing a one-time (single-level) restoration of the previous title using the 96# f_dialog_title_restore() function (below). 97# 98f_dialog_title() 99{ 100 local new_title="$1" 101 102 if [ "${1+set}" ]; then 103 if [ "$USE_XDIALOG" ]; then 104 _DIALOG_BACKTITLE="$DIALOG_BACKTITLE" 105 DIALOG_BACKTITLE="$new_title" 106 else 107 _DIALOG_TITLE="$DIALOG_TITLE" 108 DIALOG_TITLE="$new_title" 109 fi 110 else 111 if [ "$USE_XDIALOG" ]; then 112 echo "$DIALOG_BACKTITLE" 113 else 114 echo "$DIALOG_TITLE" 115 fi 116 fi 117} 118 119# f_dialog_title_restore 120# 121# Restore the previous title set by the last call to f_dialog_title(). 122# Restoration is non-recursive and only works to restore the most-recent title. 123# 124f_dialog_title_restore() 125{ 126 if [ "$USE_XDIALOG" ]; then 127 DIALOG_BACKTITLE="$_DIALOG_BACKTITLE" 128 else 129 DIALOG_TITLE="$_DIALOG_TITLE" 130 fi 131} 132 133# f_dialog_backtitle [$new_backtitle] 134# 135# Set the backtitle of future dialog(1) ($DIALOG_BACKTITLE) or title of 136# Xdialog(1) ($DIALOG_TITLE) invocations. If no arguments are given or the 137# first argument is NULL, the current backtitle is returned. 138# 139f_dialog_backtitle() 140{ 141 local new_backtitle="$1" 142 143 if [ "${1+set}" ]; then 144 if [ "$USE_XDIALOG" ]; then 145 _DIALOG_TITLE="$DIALOG_TITLE" 146 DIALOG_TITLE="$new_backtitle" 147 else 148 _DIALOG_BACKTITLE="$DIALOG_BACKTITLE" 149 DIALOG_BACKTITLE="$new_backtitle" 150 fi 151 else 152 if [ "$USE_XDIALOG" ]; then 153 echo "$DIALOG_TITLE" 154 else 155 echo "$DIALOG_BACKTITLE" 156 fi 157 fi 158} 159 160# f_dialog_backtitle_restore 161# 162# Restore the previous backtitle set by the last call to f_dialog_backtitle(). 163# Restoration is non-recursive and only works to restore the most-recent 164# backtitle. 165# 166f_dialog_backtitle_restore() 167{ 168 if [ "$USE_XDIALOG" ]; then 169 DIALOG_TITLE="$_DIALOG_TITLE" 170 else 171 DIALOG_BACKTITLE="$_DIALOG_BACKTITLE" 172 fi 173} 174 175############################################################ SIZE FUNCTIONS 176 177# f_dialog_infobox_size $title $backtitle $prompt [$hline] 178# 179# Not all versions of dialog(1) perform auto-sizing of the width and height of 180# `--infobox' boxes sensibly. 181# 182# This function helps solve this issue by taking as arguments (in order of 183# appearance) the title, backtitle, prompt, and [optionally] hline returning 184# the optimal width and height for the box (not exceeding the actual terminal 185# width or height). 186# 187# Newline character sequences (``\n'') in $prompt are expanded as-is done by 188# dialog(1). 189# 190# Output is in the format of "height width". 191# 192f_dialog_infobox_size() 193{ 194 local title="$1" btitle="$2" prompt="$3" hline="$4" n=0 195 local min_width max_size 196 197 if [ "$USE_XDIALOG" ]; then 198 min_width=35 199 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 200 else 201 min_width=24 202 max_size=$( stty size 2> /dev/null ) # usually "24 80" 203 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 204 fi 205 206 local max_height="${max_size%%[$IFS]*}" 207 local max_width="${max_size##*[$IFS]}" 208 local height width=$min_width 209 210 # 211 # Bump width for long titles (but don't exceed terminal width). 212 # 213 n=$(( ${#title} + 4 )) 214 if [ $n -gt $width -a $n -gt $min_width ]; then 215 # Add 16.6% width for Xdialog(1) 216 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) 217 218 if [ $n -lt $max_width ]; then 219 width=$n 220 else 221 width=$max_width 222 fi 223 fi 224 225 # 226 # For Xdialog(1), bump width for long backtitles (which appear within 227 # the window; don't exceed maximum width). 228 # 229 if [ "$USE_XDIALOG" ]; then 230 n=$(( ${#btitle} + 4 )) 231 n=$(( $n + $n / 6 )) 232 if [ $n -gt $width -a $n -gt $min_width ]; then 233 if [ $n -lt $max_width ]; then 234 width=$n 235 else 236 width=$max_width 237 fi 238 fi 239 fi 240 241 # 242 # Bump width for long prompts (if not already at maximum width). 243 # 244 if [ $width -lt $max_width ]; then 245 n=$( echo "$prompt" | f_longest_line_length ) 246 n=$(( $n + 4 )) 247 248 # Add 16.6% width for Xdialog(1) 249 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) 250 251 if [ $n -gt $width -a $n -gt $min_width ]; then 252 if [ $n -lt $max_width ]; then 253 width=$n 254 else 255 width=$max_width 256 fi 257 fi 258 fi 259 260 # 261 # Bump width for long hlines (if not already at maximum width). 262 # NOTE: Though Xdialog(1) supports `--hline', it's not currently used. 263 # 264 if [ ! "$USE_XDIALOG" ]; then 265 if [ $width -lt $max_width ]; then 266 n=$(( ${#hline} + 10 )) 267 if [ $n -gt $width -a $n -gt $min_width ]; then 268 if [ $n -lt $max_width ]; then 269 width=$n 270 else 271 width=$max_width 272 fi 273 fi 274 fi 275 fi 276 277 # 278 # Set height based on number of rows in prompt 279 # 280 height=$( echo -n "$prompt" | f_number_of_lines ) 281 height=$(( $height + 2 )) 282 283 # 284 # For Xdialog(1) bump height if backtitle is enabled (displayed in the 285 # X11 window with a separator line between the backtitle and msg text) 286 # 287 if [ "$USE_XDIALOG" -a "$btitle" ]; then 288 n=$( echo "$btitle" | f_number_of_lines ) 289 height=$(( $height + $n + 2 )) 290 fi 291 292 # Make sure height is less than maximum screen size 293 [ $height -le $max_height ] || height=$max_height 294 295 # Return both 296 echo "$height $width" 297} 298 299# f_dialog_buttonbox_size $title $backtitle $prompt [$hline] 300# 301# Not all versions of dialog(1) perform auto-sizing of the width and height of 302# `--msgbox' and `--yesno' boxes sensibly. 303# 304# This function helps solve this issue by taking as arguments (in order of 305# appearance) the title, backtitle, prompt, and [optionally] hline returning 306# the optimal width and height for the box (not exceeding the actual terminal 307# width or height). 308# 309# Newline character sequences (``\n'') in $prompt are expanded as-is done by 310# dialog(1). 311# 312# Output is in the format of "height width". 313# 314f_dialog_buttonbox_size() 315{ 316 local title="$1" btitle="$2" prompt="$3" hline="$4" 317 local size="$( f_dialog_infobox_size \ 318 "$title" "$btitle" "$prompt" "$hline" )" 319 local height="${size%%[$IFS]*}" 320 local width="${size##*[$IFS]}" 321 322 # Add height to accomodate the buttons 323 height=$(( $height + 2 )) 324 325 # Adjust for clipping with Xdialog(1) on Linux/GTK2 326 [ "$USE_XDIALOG" ] && height=$(( $height + 3 )) 327 328 # 329 # Enforce maximum height regardless 330 # 331 local max_size 332 if [ "$USE_XDIALOG" ]; then 333 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 334 else 335 max_size=$( stty size 2> /dev/null ) # usually "24 80" 336 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 337 fi 338 local max_height="${max_size%%[$IFS]*}" 339 [ $height -le $max_height ] || height=$max_height 340 341 # Return both 342 echo "$height $width" 343} 344 345# f_dialog_inputbox_size $title $backtitle $prompt $init [$hline] 346# 347# Not all versions of dialog(1) perform auto-sizing of the width and height of 348# `--inputbox' boxes sensibly. 349# 350# This function helps solve this issue by taking as arguments (in order of 351# appearance) the title, backtitle, prompt, initial text, and [optionally] 352# hline returning the optimal width and height for the box (not exceeding the 353# actual terminal width and height). 354# 355# Newline character sequences (``\n'') in $prompt are expanded as-is done by 356# dialog(1). 357# 358# Output is in the format of "height width". 359# 360f_dialog_inputbox_size() 361{ 362 local title="$1" btitle="$2" prompt="$3" init="$4" hline="$5" n 363 local size="$( f_dialog_buttonbox_size \ 364 "$title" "$btitle" "$prompt" "$hline" )" 365 local height="${size%%[$IFS]*}" 366 local width="${size##*[$IFS]}" 367 368 local min_width max_size 369 if [ "$USE_XDIALOG" ]; then 370 min_width=35 371 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 372 else 373 min_width=24 374 max_size=$( stty size 2> /dev/null ) # usually "24 80" 375 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 376 fi 377 local max_height="${max_size%%[$IFS]*}" 378 local max_width="${max_size##*[$IFS]}" 379 380 # 381 # Add height to accomodate the input box 382 # 383 [ ! "$USE_XDIALOG" ] && height=$(( $height + 3 )) 384 [ $height -le $max_height ] || height=$max_height 385 386 # 387 # Bump width for initial text (if not already at maximum width). 388 # NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it! 389 # 390 if [ $width -lt $max_width ]; then 391 n=$(( ${#init} + 7 )) 392 393 # Add 16.6% width for Xdialog(1) 394 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) 395 396 if [ $n -gt $width -a $n -gt $min_width ]; then 397 if [ $n -lt $max_width ]; then 398 width=$n 399 else 400 width=$max_width 401 fi 402 fi 403 fi 404 405 # Return both 406 echo "$height $width" 407} 408 409# f_xdialog_2inputsbox_size $title $backtitle $prompt \ 410# $label1 $init1 $label2 $init2 411# 412# Xdialog(1) does not perform auto-sizing of the width and height of 413# `--2inputsbox' boxes sensibly. 414# 415# This function helps solve this issue by taking as arguments (in order of 416# appearance) the title, backtitle, prompt, label for the first field, initial 417# text for said field, label for the second field, and initial text for said 418# field returning the optimal width and height for the box (not exceeding the 419# actual terminal width and height). 420# 421# Newline character sequences (``\n'') in $prompt are expanded as-is done by 422# Xdialog(1). 423# 424# Output is in the format of "height width". 425# 426f_xdialog_2inputsbox_size() 427{ 428 local title="$1" btitle="$2" prompt="$3" 429 local label1="$4" init1="$5" label2="$6" init2="$7" n 430 local size="$( f_dialog_inputbox_size \ 431 "$title" "$btitle" "$prompt" "$init1" )" 432 local height="${size%%[$IFS]*}" 433 local width="${size##*[$IFS]}" 434 435 local min_width=35 436 local max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 437 local max_height="${max_size%%[$IFS]*}" 438 local max_width="${max_size##*[$IFS]}" 439 440 # Add height for first label 441 height=$(( $height + 2 )) 442 443 # 444 # Bump width for first label text (if not already at maximum width). 445 # 446 if [ $width -lt $max_width ]; then 447 n=$(( ${#label1} + 7 )) 448 449 # Add 16.6% width for Xdialog(1) 450 n=$(( $n + $n / 6 )) 451 452 if [ $n -gt $width -a $n -gt $min_width ]; then 453 if [ $n -lt $max_width ]; then 454 width=$n 455 else 456 width=$max_width 457 fi 458 fi 459 fi 460 461 # Add height for second label 462 height=$(( $height + 2 )) 463 464 # 465 # Bump width for second label text (if not already at maximum width). 466 # 467 if [ $width -lt $max_width ]; then 468 n=$(( ${#label2} + 7 )) 469 470 # Add 16.6% width for Xdialog(1) 471 n=$(( $n + $n / 6 )) 472 473 if [ $n -gt $width -a $n -gt $min_width ]; then 474 if [ $n -lt $max_width ]; then 475 width=$n 476 else 477 width=$max_width 478 fi 479 fi 480 fi 481 482 # Add height for a second inputbox 483 height=$(( $height + 2 )) 484 [ $height -le $max_height ] || height=$max_height 485 486 # 487 # Bump width for second initial text (if not already at maximum width). 488 # NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it! 489 # 490 if [ $width -lt $max_width ]; then 491 n=$(( ${#init2} + 7 )) 492 493 # Add 16.6% width for Xdialog(1) 494 n=$(( $n + $n / 6 )) 495 496 if [ $n -gt $width -a $n -gt $min_width ]; then 497 if [ $n -lt $max_width ]; then 498 width=$n 499 else 500 width=$max_width 501 fi 502 fi 503 fi 504 505 # Return both 506 echo "$height $width" 507} 508 509# f_dialog_menu_size $title $backtitle $prompt $hline \ 510# $tag1 $item1 $tag2 $item2 ... 511# 512# Not all versions of dialog(1) perform auto-sizing of the width and height of 513# `--menu' boxes sensibly. 514# 515# This function helps solve this issue by taking as arguments (in order of 516# appearance) the title, backtitle, prompt, hline and list of tag/item pairs, 517# returning the optimal width and height for the menu (not exceeding the actual 518# terminal width or height). 519# 520# Output is in the format of "height width rows". 521# 522f_dialog_menu_size() 523{ 524 local title="$1" btitle="$2" prompt="$3" hline="$4" n=0 525 local min_width min_rows max_size 526 527 if [ "$USE_XDIALOG" ]; then 528 min_width=35 529 min_rows=1 530 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 531 else 532 min_width=24 533 min_rows=0 534 max_size=$( stty size 2> /dev/null ) # usually "24 80" 535 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 536 fi 537 538 local max_width="${max_size##*[$IFS]}" 539 local max_height="${max_size%%[$IFS]*}" 540 local box_size="$( f_dialog_infobox_size \ 541 "$title" "$btitle" "$prompt" "$hline" )" 542 local box_height="${box_size%%[$IFS]*}" 543 local box_width="${box_size##*[$IFS]}" 544 local max_rows=$(( $max_height - 8 )) 545 local height width=$box_width rows=$min_rows 546 547 shift 4 # title/btitle/prompt/hline 548 549 # If there's no prompt, bump the max-rows by 1 550 [ "$prompt" ] || max_rows=$(( $max_rows + 1 )) 551 552 # 553 # The sum total between the longest tag-length and longest item-length 554 # should be used for the menu width (not to exceed terminal width). 555 # 556 # Also, calculate the number of rows (not to exceed terminal height). 557 # 558 local longest_tag=0 longest_item=0 559 while [ $# -ge 2 ]; do 560 local tag="$1" item="$2" 561 shift 2 # tag/item 562 563 [ ${#tag} -gt $longest_tag ] && longest_tag=${#tag} 564 [ ${#item} -gt $longest_item ] && longest_item=${#item} 565 [ $rows -lt $max_rows ] && rows=$(( $rows + 1 )) 566 done 567 568 # Update width 569 n=$(( $longest_tag + $longest_item + 10 )) 570 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1) 571 if [ $n -gt $width -a $n -gt $min_width ]; then 572 if [ $n -lt $max_width ]; then 573 width=$n 574 else 575 width=$max_width 576 fi 577 fi 578 579 # Fix rows and set height 580 [ $rows -gt 0 ] || rows=1 581 if [ "$USE_XDIALOG" ]; then 582 height=$(( $rows + $box_height + 7 )) 583 else 584 height=$(( $rows + $box_height + 4 )) 585 fi 586 [ $height -le $max_height ] || height=$max_height 587 588 # Return all three 589 echo "$height $width $rows" 590} 591 592# f_dialog_menu_with_help_size $title $backtitle $prompt $hline \ 593# $tag1 $item1 $help1 $tag2 $item2 $help2 ... 594# 595# Not all versions of dialog(1) perform auto-sizing of the width and height of 596# `--menu' boxes sensibly. 597# 598# This function helps solve this issue by taking as arguments (in order of 599# appearance) the title, backtitle, prompt, hline and list of tag/item/help 600# triplets, returning the optimal width and height for the menu (not exceeding 601# the actual terminal width or height). 602# 603# Output is in the format of "height width rows". 604# 605f_dialog_menu_with_help_size() 606{ 607 local title="$1" btitle="$2" prompt="$3" hline="$4" n=0 608 local min_width min_rows max_size 609 610 if [ "$USE_XDIALOG" ]; then 611 min_width=35 612 min_rows=1 613 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 614 else 615 min_width=24 616 min_rows=0 617 max_size=$( stty size 2> /dev/null ) # usually "24 80" 618 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 619 fi 620 621 local max_width="${max_size##*[$IFS]}" 622 local max_height="${max_size%%[$IFS]*}" 623 local box_size="$( f_dialog_infobox_size \ 624 "$title" "$btitle" "$prompt" "$hline" )" 625 local box_height="${box_size%%[$IFS]*}" 626 local box_width="${box_size##*[$IFS]}" 627 local max_rows=$(( $max_height - 8 )) 628 local height width=$box_width rows=$min_rows 629 630 shift 4 # title/btitle/prompt/hline 631 632 # If there's no prompt, bump the max-rows by 1 633 [ "$prompt" ] || max_rows=$(( $max_rows + 1 )) 634 635 # 636 # The sum total between the longest tag-length and longest item-length 637 # should be used for the menu width (not to exceed terminal width). 638 # 639 # Also, calculate the number of rows (not to exceed terminal height). 640 # 641 # Also, calculate the longest help while we're here. This will be used 642 # to influence the width of the menu if (and only-if) using Xdialog(1). 643 # 644 local longest_tag=0 longest_item=0 longest_help=0 645 while [ $# -ge 3 ]; do 646 local tag="$1" item="$2" help="$3" 647 shift 3 # tag/item/help 648 649 [ ${#tag} -gt $longest_tag ] && longest_tag=${#tag} 650 [ ${#item} -gt $longest_item ] && longest_item=${#item} 651 [ ${#help} -gt $longest_help ] && longest_help=${#help} 652 [ $rows -lt $max_rows ] && rows=$(( $rows + 1 )) 653 done 654 655 # Update width 656 n=$(( $longest_tag + $longest_item + 10 )) 657 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1) 658 if [ $n -gt $width -a $n -gt $min_width ]; then 659 if [ $n -lt $max_width ]; then 660 width=$n 661 else 662 width=$max_width 663 fi 664 fi 665 666 # Update width for help text if using Xdialog(1) 667 if [ "$USE_XDIALOG" ]; then 668 n=$(( $longest_help + 10 )) 669 n=$(( $n + $n / 6 )) # +16.6% 670 if [ $n -gt $width -a $n -gt $min_width ]; then 671 if [ $n -lt $max_width ]; then 672 width=$n 673 else 674 width=$max_width 675 fi 676 fi 677 fi 678 679 # Fix rows and set height 680 [ $rows -gt 0 ] || rows=1 681 if [ "$USE_XDIALOG" ]; then 682 height=$(( $rows + $box_height + 8 )) 683 else 684 height=$(( $rows + $box_height + 4 )) 685 fi 686 [ $height -le $max_height ] || height=$max_height 687 688 # Return all three 689 echo "$height $width $rows" 690} 691 692# f_dialog_radiolist_size $title $backtitle $prompt $hline \ 693# $tag1 $item1 $status1 $tag2 $item2 $status2 ... 694# 695# Not all versions of dialog(1) perform auto-sizing of the width and height of 696# `--radiolist' boxes sensibly. 697# 698# This function helps solve this issue by taking as arguments (in order of 699# appearance) the title, backtitle, prompt, hline and list of tag/item/status 700# triplets, returning the optimal width and height for the radiolist (not 701# exceeding the actual terminal width or height). 702# 703# Output is in the format of "height width rows". 704# 705f_dialog_radiolist_size() 706{ 707 local title="$1" btitle="$2" prompt="$3" hline="$4" n=0 708 local min_width min_rows max_size 709 710 if [ "$USE_XDIALOG" ]; then 711 min_width=35 712 min_rows=1 713 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 714 else 715 min_width=24 716 min_rows=0 717 max_size=$( stty size 2> /dev/null ) # usually "24 80" 718 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 719 fi 720 721 local max_width="${max_size##*[$IFS]}" 722 local max_height="${max_size%%[$IFS]*}" 723 local box_size="$( f_dialog_infobox_size \ 724 "$title" "$btitle" "$prompt" "$hline" )" 725 local box_height="${box_size%%[$IFS]*}" 726 local box_width="${box_size##*[$IFS]}" 727 local max_rows=$(( $max_height - 8 )) 728 local height width=$box_width rows=$min_rows 729 730 shift 4 # title/btitle/prompt/hline 731 732 # 733 # The sum total between the longest tag-length, longest item-length, 734 # and radio-button width should be used for the menu width (not to 735 # exceed terminal width). 736 # 737 # Also, calculate the number of rows (not to exceed terminal height). 738 # 739 local longest_tag=0 longest_item=0 740 while [ $# -ge 3 ]; do 741 local tag="$1" item="$2" 742 shift 3 # tag/item/status 743 744 [ ${#tag} -gt $longest_tag ] && longest_tag=${#tag} 745 [ ${#item} -gt $longest_item ] && longest_item=${#item} 746 [ $rows -lt $max_rows ] && rows=$(( $rows + 1 )) 747 done 748 749 # Update width 750 n=$(( $longest_tag + $longest_item + 13 )) 751 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1) 752 if [ $n -gt $width -a $n -gt $min_width ]; then 753 if [ $n -lt $max_width ]; then 754 width=$n 755 else 756 width=$max_width 757 fi 758 fi 759 760 # Fix rows and set height 761 [ $rows -gt 0 ] || rows=1 762 if [ "$USE_XDIALOG" ]; then 763 height=$(( $rows + $box_height + 7 )) 764 else 765 height=$(( $rows + $box_height + 4 )) 766 fi 767 [ $height -le $max_height ] || height=$max_height 768 769 # Return all three 770 echo "$height $width $rows" 771} 772 773# f_dialog_checklist_size $title $backtitle $prompt $hline \ 774# $tag1 $item1 $status1 $tag2 $item2 $status2 ... 775# 776# Not all versions of dialog(1) perform auto-sizing of the width and height of 777# `--checklist' boxes sensibly. 778# 779# This function helps solve this issue by taking as arguments (in order of 780# appearance) the title, backtitle, prompt, hline and list of tag/item/status 781# triplets, returning the optimal width and height for the checklist (not 782# exceeding the actual terminal width or height). 783# 784# Output is in the format of "height width rows". 785# 786f_dialog_checklist_size() 787{ 788 f_dialog_radiolist_size "$@" 789} 790 791# f_dialog_radiolist_with_help_size $title $backtitle $prompt $hline \ 792# $tag1 $item1 $status1 $help1 \ 793# $tag2 $item2 $status2 $help2 ... 794# 795# Not all versions of dialog(1) perform auto-sizing of the width and height of 796# `--radiolist' boxes sensibly. 797# 798# This function helps solve this issue by taking as arguments (in order of 799# appearance) the title, backtitle, prompt, hline and list of 800# tag/item/status/help quads, returning the optimal width and height for the 801# radiolist (not exceeding the actual terminal width or height). 802# 803# Output is in the format of "height width rows". 804# 805f_dialog_radiolist_with_help_size() 806{ 807 local title="$1" btitle="$2" prompt="$3" hline="$4" n=0 808 local min_width min_rows max_size 809 810 if [ "$USE_XDIALOG" ]; then 811 min_width=35 812 min_rows=1 813 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 814 else 815 min_width=24 816 min_rows=0 817 max_size=$( stty size 2> /dev/null ) # usually "24 80" 818 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 819 fi 820 821 local max_width="${max_size##*[$IFS]}" 822 local max_height="${max_size%%[$IFS]*}" 823 local box_size="$( f_dialog_infobox_size \ 824 "$title" "$btitle" "$prompt" "$hline" )" 825 local box_height="${box_size%%[$IFS]*}" 826 local box_width="${box_size##*[$IFS]}" 827 local max_rows=$(( $max_height - 8 )) 828 local height width=$box_width rows=$min_rows 829 830 shift 4 # title/btitle/prompt/hline 831 832 # 833 # The sum total between the longest tag-length, longest item-length, 834 # and radio-button width should be used for the menu width (not to 835 # exceed terminal width). 836 # 837 # Also, calculate the number of rows (not to exceed terminal height). 838 # 839 # Also, calculate the longest help while we're here. This will be used 840 # to influence the width of the menu if (and only-if) using Xdialog(1). 841 # 842 local longest_tag=0 longest_item=0 longest_help=0 843 while [ $# -ge 4 ]; do 844 local tag="$1" item="$2" status="$3" help="$4" 845 shift 4 # tag/item/status/help 846 847 [ ${#tag} -gt $longest_tag ] && longest_tag=${#tag} 848 [ ${#item} -gt $longest_item ] && longest_item=${#item} 849 [ ${#help} -gt $longest_help ] && longest_help=${#help} 850 [ $rows -lt $max_rows ] && rows=$(( $rows + 1 )) 851 done 852 853 # Update width 854 n=$(( $longest_tag + $longest_item + 13 )) 855 [ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1) 856 if [ $n -gt $width -a $n -gt $min_width ]; then 857 if [ $n -lt $max_width ]; then 858 width=$n 859 else 860 width=$max_width 861 fi 862 fi 863 864 # Update width for help text if using Xdialog(1) 865 if [ "$USE_XDIALOG" ]; then 866 n=$(( $longest_help + 10 )) 867 n=$(( $n + $n / 6 )) # +16.6% 868 if [ $n -gt $width -a $n -gt $min_width ]; then 869 if [ $n -lt $max_width ]; then 870 width=$n 871 else 872 width=$max_width 873 fi 874 fi 875 fi 876 877 # Fix rows and set height 878 [ $rows -gt 0 ] || rows=1 879 if [ "$USE_XDIALOG" ]; then 880 height=$(( $rows + $box_height + 7 )) 881 else 882 height=$(( $rows + $box_height + 4 )) 883 fi 884 [ $height -le $max_height ] || height=$max_height 885 886 # Return all three 887 echo "$height $width $rows" 888} 889 890# f_dialog_checklist_with_help_size $title $backtitle $prompt $hline \ 891# $tag1 $item1 $status1 $help1 \ 892# $tag2 $item2 $status2 $help2 ... 893# 894# Not all versions of dialog(1) perform auto-sizing of the width and height of 895# `--checklist' boxes sensibly. 896# 897# This function helps solve this issue by taking as arguments (in order of 898# appearance) the title, backtitle, prompt, hline and list of 899# tag/item/status/help quads, returning the optimal width and height for the 900# checklist (not exceeding the actual terminal width or height). 901# 902# Output is in the format of "height width rows". 903# 904f_dialog_checklist_with_help_size() 905{ 906 f_dialog_radiolist_with_help_size "$@" 907} 908 909# f_dialog_calendar_size $title $backtitle $prompt [$hline] 910# 911# Not all versions of dialog(1) perform auto-sizing of the width and height of 912# `--calendar' boxes sensibly. 913# 914# This function helps solve this issue by taking as arguments (in order of 915# appearance) the title, backtitle, prompt, and [optionally] hline returning 916# the optimal width and height for the box (not exceeding the actual terminal 917# width and height). 918# 919# Newline character sequences (``\n'') in $prompt are expanded as-is done by 920# dialog(1). 921# 922# Output is in the format of "height width". 923# 924f_dialog_calendar_size() 925{ 926 local title="$1" btitle="$2" prompt="$3" hline="$4" n 927 local size="$( f_dialog_infobox_size \ 928 "$title" "$btitle" "$prompt" "$hline" )" 929 local height="${size%%[$IFS]*}" 930 local width="${size##*[$IFS]}" 931 932 local min_width min_height max_size 933 if [ "$USE_XDIALOG" ]; then 934 min_height=15 935 min_width=55 936 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 937 else 938 min_height=0 939 min_width=40 940 max_size=$( stty size 2> /dev/null ) # usually "24 80" 941 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 942 fi 943 local max_height="${max_size%%[$IFS]*}" 944 local max_width="${max_size##*[$IFS]}" 945 946 # 947 # Enforce the minimum width for displaying the calendar 948 # 949 [ $width -ge $min_width ] || width=$min_width 950 951 # 952 # When using dialog(1), the calendar box is unique from other dialog(1) 953 # boxes in-that the height passed should not accomodate the 15-lines 954 # required to display the calendar. This does not apply to Xdialog(1). 955 # 956 # When using Xdialog(1), the height must accomodate the 15-lines 957 # required to display the calendar. 958 # 959 # NOTE: Also under dialog(1), because we can't predict whether the user 960 # has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract 961 # 16 rather than 15. This does not apply to Xdialog(1). 962 # 963 max_height=$(( $max_height - 16 )) 964 height=$( echo "$prompt" | f_number_of_lines ) 965 if [ "$USE_XDIALOG" ]; then 966 # Add height to accomodate for the embedded calendar widget 967 height=$(( $height + $min_height - 1 )) 968 969 # Also, bump height if backtitle is enabled 970 if [ "$btitle" ]; then 971 local n="$( echo "$btitle" | f_number_of_lines )" 972 height=$(( $height + $n + 2 )) 973 fi 974 else 975 [ "$prompt" ] && height=$(( $height + 1 )) 976 fi 977 [ $height -le $max_height ] || height=$max_height 978 979 # 980 # The calendar box refuses to display if too large. 981 # 982 max_width=$(( $max_width - 2 )) 983 [ $width -le $max_width ] || width=$max_width 984 985 # Return both 986 echo "$height $width" 987} 988 989# f_dialog_timebox_size $title $backtitle $prompt [$hline] 990# 991# Not all versions of dialog(1) perform auto-sizing of the width and height of 992# `--timebox' boxes sensibly. 993# 994# This function helps solve this issue by taking as arguments (in order of 995# appearance) the title, backtitle, prompt, and [optionally] hline returning 996# the optimal width and height for the box (not exceeding the actual terminal 997# width and height). 998# 999# Newline character sequences (``\n'') in $prompt are expanded as-is done by 1000# dialog(1). 1001# 1002# Output is in the format of "height width". 1003# 1004f_dialog_timebox_size() 1005{ 1006 local title="$1" btitle="$2" prompt="$3" hline="$4" n 1007 local size="$( f_dialog_infobox_size \ 1008 "$title" "$btitle" "$prompt" "$hline" )" 1009 local height="${size%%[$IFS]*}" 1010 local width="${size##*[$IFS]}" 1011 1012 local min_width min_height max_size 1013 if [ "$USE_XDIALOG" ]; then 1014 min_width=40 1015 max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION 1016 else 1017 min_height=0 1018 min_width=20 1019 max_size=$( stty size 2> /dev/null ) # usually "24 80" 1020 : ${max_size:=$DEFAULT_TERMINAL_SIZE} 1021 fi 1022 local max_height="${max_size%%[$IFS]*}" 1023 local max_width="${max_size##*[$IFS]}" 1024 1025 # 1026 # Enforce the minimum width for displaying the timebox 1027 # 1028 [ $width -ge $min_width ] || width=$min_width 1029 1030 # 1031 # When using dialog(1), the timebox box is unique from other dialog(1) 1032 # boxes in-that the height passed should not accomodate the 6-lines 1033 # required to display the timebox. This does not apply to Xdialog(1). 1034 # 1035 # When using Xdialog(1), the height seems to have no effect. All values 1036 # provide the same results. 1037 # 1038 # NOTE: Also under dialog(1), because we can't predict whether the user 1039 # has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract 1040 # 7 rather than 6. This does not apply to Xdialog(1). 1041 # 1042 if [ "$USE_XDIALOG" ]; then 1043 height=0 # Autosize; all values produce same results 1044 else 1045 max_height=$(( $max_height - 7 )) 1046 height=$( echo "$prompt" | f_number_of_lines ) 1047 height=$(( $height + 1 )) 1048 [ $height -le $max_height ] || height=$max_height 1049 [ "$prompt" ] && height=$(( $height + 1 )) 1050 fi 1051 1052 # 1053 # The timebox box refuses to display if too large. 1054 # 1055 max_width=$(( $max_width - 2 )) 1056 [ $width -le $max_width ] || width=$max_width 1057 1058 # Return both 1059 echo "$height $width" 1060} 1061 1062############################################################ CLEAR FUNCTIONS 1063 1064# f_dialog_clear 1065# 1066# Clears any/all previous dialog(1) displays. 1067# 1068f_dialog_clear() 1069{ 1070 $DIALOG --clear 1071} 1072 1073############################################################ INFO FUNCTIONS 1074 1075# f_dialog_info $info_text ... 1076# 1077# Throw up a dialog(1) infobox. The infobox remains until another dialog is 1078# displayed or `dialog --clear' (or f_dialog_clear) is called. 1079# 1080f_dialog_info() 1081{ 1082 local info_text="$*" 1083 local size="$( f_dialog_infobox_size \ 1084 "$DIALOG_TITLE" \ 1085 "$DIALOG_BACKTITLE" \ 1086 "$info_text" )" 1087 1088 eval $DIALOG \ 1089 --title \"\$DIALOG_TITLE\" \ 1090 --backtitle \"\$DIALOG_BACKTITLE\" \ 1091 ${USE_XDIALOG:+--ignore-eof} \ 1092 ${USE_XDIALOG:+--no-buttons} \ 1093 --infobox \"\$info_text\" $size 1094} 1095 1096# f_xdialog_info $info_text ... 1097# 1098# Throw up an Xdialog(1) infobox and do not dismiss it until stdin produces 1099# EOF. This implies that you must execute this either as an rvalue to a pipe, 1100# lvalue to indirection or in a sub-shell that provides data on stdin. 1101# 1102f_xdialog_info() 1103{ 1104 local info_text="$*" 1105 local size="$( f_dialog_infobox_size \ 1106 "$DIALOG_TITLE" \ 1107 "$DIALOG_BACKTITLE" \ 1108 "$info_text" )" 1109 1110 eval $DIALOG \ 1111 --title \"\$DIALOG_TITLE\" \ 1112 --backtitle \"\$DIALOG_BACKTITLE\" \ 1113 --no-close --no-buttons \ 1114 --infobox \"\$info_text\" $size \ 1115 -1 # timeout of -1 means abort when EOF on stdin 1116} 1117 1118############################################################ MSGBOX FUNCTIONS 1119 1120# f_dialog_msgbox $msg_text ... 1121# 1122# Throw up a dialog(1) msgbox. The msgbox remains until the user presses ENTER 1123# or ESC, acknowledging the modal dialog. 1124# 1125# If the user presses ENTER, the exit status is zero (success), otherwise if 1126# the user presses ESC the exit status is 255. 1127# 1128f_dialog_msgbox() 1129{ 1130 local msg_text="$*" 1131 local size="$( f_dialog_buttonbox_size \ 1132 "$DIALOG_TITLE" \ 1133 "$DIALOG_BACKTITLE" \ 1134 "$msg_text" )" 1135 1136 eval $DIALOG \ 1137 --title \"\$DIALOG_TITLE\" \ 1138 --backtitle \"\$DIALOG_BACKTITLE\" \ 1139 --ok-label \"\$msg_ok\" \ 1140 --msgbox \"\$msg_text\" $size 1141} 1142 1143############################################################ TEXTBOX FUNCTIONS 1144 1145# f_dialog_textbox $file 1146# 1147# Display the contents of $file (or an error if $file does not exist, etc.) in 1148# a dialog(1) textbox (which has a scrollable region for the text). The textbox 1149# remains until the user presses ENTER or ESC, acknowledging the modal dialog. 1150# 1151# If the user presses ENTER, the exit status is zero (success), otherwise if 1152# the user presses ESC the exit status is 255. 1153# 1154f_dialog_textbox() 1155{ 1156 local file="$1" 1157 local contents retval size 1158 1159 contents=$( cat "$file" 2>&1 ) 1160 retval=$? 1161 1162 size=$( f_dialog_buttonbox_size \ 1163 "$DIALOG_TITLE" \ 1164 "$DIALOG_BACKTITLE" \ 1165 "$contents" ) 1166 1167 if [ $retval -eq $SUCCESS ]; then 1168 eval $DIALOG \ 1169 --title \"\$DIALOG_TITLE\" \ 1170 --backtitle \"\$DIALOG_BACKTITLE\" \ 1171 --exit-label \"\$msg_ok\" \ 1172 --no-cancel \ 1173 --textbox \"\$file\" $size 1174 else 1175 eval $DIALOG \ 1176 --title \"\$DIALOG_TITLE\" \ 1177 --backtitle \"\$DIALOG_BACKTITLE\" \ 1178 --ok-label \"\$msg_ok\" \ 1179 --msgbox \"\$contents\" $size 1180 fi 1181} 1182 1183############################################################ YESNO FUNCTIONS 1184 1185# f_dialog_yesno $msg_text ... 1186# 1187# Display a dialog(1) Yes/No prompt to allow the user to make some decision. 1188# The yesno prompt remains until the user presses ENTER or ESC, acknowledging 1189# the modal dialog. 1190# 1191# If the user chooses YES the exit status is zero, or chooses NO the exit 1192# status is one, or presses ESC the exit status is 255. 1193# 1194f_dialog_yesno() 1195{ 1196 local msg_text="$*" 1197 local hline="$hline_arrows_tab_enter" 1198 1199 f_interactive || return 0 # If non-interactive, return YES all the time 1200 1201 local size="$( f_dialog_buttonbox_size \ 1202 "$DIALOG_TITLE" \ 1203 "$DIALOG_BACKTITLE" \ 1204 "$msg_text" \ 1205 "$hline" )" 1206 1207 if [ "$USE_XDIALOG" ]; then 1208 eval $DIALOG \ 1209 --title \"\$DIALOG_TITLE\" \ 1210 --backtitle \"\$DIALOG_BACKTITLE\" \ 1211 --hline \"\$hline\" \ 1212 --ok-label \"\$msg_yes\" \ 1213 --cancel-label \"\$msg_no\" \ 1214 --yesno \"\$msg_text\" $size 1215 else 1216 eval $DIALOG \ 1217 --title \"\$DIALOG_TITLE\" \ 1218 --backtitle \"\$DIALOG_BACKTITLE\" \ 1219 --hline \"\$hline\" \ 1220 --yes-label \"\$msg_yes\" \ 1221 --no-label \"\$msg_no\" \ 1222 --yesno \"\$msg_text\" $size 1223 fi 1224} 1225 1226# f_dialog_noyes $msg_text ... 1227# 1228# Display a dialog(1) No/Yes prompt to allow the user to make some decision. 1229# The noyes prompt remains until the user presses ENTER or ESC, acknowledging 1230# the modal dialog. 1231# 1232# If the user chooses YES the exit status is zero, or chooses NO the exit 1233# status is one, or presses ESC the exit status is 255. 1234# 1235# NOTE: This is just like the f_dialog_yesno function except "No" is default. 1236# 1237f_dialog_noyes() 1238{ 1239 local msg_text="$*" 1240 local hline="$hline_arrows_tab_enter" 1241 1242 f_interactive || return 1 # If non-interactive, return NO all the time 1243 1244 local size="$( f_dialog_buttonbox_size \ 1245 "$DIALOG_TITLE" \ 1246 "$DIALOG_BACKTITLE" \ 1247 "$msg_text" \ 1248 "$hline" )" 1249 1250 if [ "$USE_XDIALOG" ]; then 1251 eval $DIALOG \ 1252 --title \"\$DIALOG_TITLE\" \ 1253 --backtitle \"\$DIALOG_BACKTITLE\" \ 1254 --hline \"\$hline\" \ 1255 --default-no \ 1256 --ok-label \"\$msg_yes\" \ 1257 --cancel-label \"\$msg_no\" \ 1258 --yesno \"\$msg_text\" $size 1259 else 1260 eval $DIALOG \ 1261 --title \"\$DIALOG_TITLE\" \ 1262 --backtitle \"\$DIALOG_BACKTITLE\" \ 1263 --hline \"\$hline\" \ 1264 --defaultno \ 1265 --yes-label \"\$msg_yes\" \ 1266 --no-label \"\$msg_no\" \ 1267 --yesno \"\$msg_text\" $size 1268 fi 1269} 1270 1271############################################################ INPUT FUNCTIONS 1272 1273# f_dialog_inputstr 1274# 1275# Obtain the inputstr entered by the user from the most recently displayed 1276# dialog(1) inputbox and clean up any temporary files/variables. 1277# 1278f_dialog_inputstr() 1279{ 1280 # Skip warnings and trim leading/trailing whitespace from user input 1281 eval echo \"\$DIALOG_INPUTBOX_$$\" | awk ' 1282 BEGIN { found = 0 } 1283 { 1284 if ( ! found ) 1285 { 1286 if ( $0 ~ /^$/ ) next 1287 if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next 1288 found = 1 1289 } 1290 sub(/^[[:space:]]*/, "") 1291 sub(/[[:space:]]*$/, "") 1292 print 1293 } 1294 ' 1295 setvar DIALOG_INPUTBOX_$$ "" # scrub memory in case data was sensitive 1296 return $SUCCESS 1297} 1298 1299# f_dialog_input $prompt [$init [$hline]] 1300# 1301# Prompt the user with a dialog(1) inputbox to enter some value. The inputbox 1302# remains until the the user presses ENTER or ESC, or otherwise ends the 1303# editing session, by selecting `Cancel' for example. 1304# 1305# If the user presses ENTER, the exit status is zero (success), otherwise if 1306# the user presses ESC the exit status is 255, or if the user chose Cancel, the 1307# exit status is instead 1. 1308# 1309# NOTE: The hline should correspond to the type of data you want from the user. 1310# NOTE: Should not be used to edit multiline values. 1311# 1312f_dialog_input() 1313{ 1314 local prompt="$1" init="$2" hline="$3" 1315 local size="$( f_dialog_inputbox_size \ 1316 "$DIALOG_TITLE" \ 1317 "$DIALOG_BACKTITLE" \ 1318 "$prompt" \ 1319 "$init" \ 1320 "$hline" )" 1321 1322 local opterm="--" 1323 [ "$USE_XDIALOG" ] && opterm= 1324 1325 local dialog_input 1326 dialog_input=$( 1327 eval $DIALOG \ 1328 --title \"\$DIALOG_TITLE\" \ 1329 --backtitle \"\$DIALOG_BACKTITLE\" \ 1330 --hline \"\$hline\" \ 1331 --ok-label \"\$msg_ok\" \ 1332 --cancel-label \"\$msg_cancel\" \ 1333 --inputbox \"\$prompt\" $size \ 1334 $opterm \"\$init\" \ 1335 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 1336 ) 1337 local retval=$? 1338 1339 setvar DIALOG_INPUTBOX_$$ "$dialog_input" 1340 f_dialog_inputstr 1341 1342 return $retval 1343} 1344 1345############################################################ MENU FUNCTIONS 1346 1347# f_dialog_menutag 1348# 1349# Obtain the menutag chosen by the user from the most recently displayed 1350# dialog(1) menu and clean up any temporary files/variables. 1351# 1352f_dialog_menutag() 1353{ 1354 # Skip warnings 1355 eval echo \"\$DIALOG_MENU_$$\" | awk ' 1356 BEGIN { found = 0 } 1357 { 1358 if ( found ) # ... just spew 1359 { 1360 print 1361 next 1362 } 1363 if ( $0 ~ /^$/ ) next 1364 if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next 1365 found = 1 1366 print 1367 } 1368 ' 1369 setvar DIALOG_MENU_$$ "" # scrub memory in case data was sensitive 1370 return $SUCCESS 1371} 1372 1373# f_dialog_menutag2item $tag_chosen $tag1 $item1 $tag2 $item2 ... 1374# 1375# To use the `--menu' option of dialog(1) you must pass an ordered list of 1376# tag/item pairs on the command-line. When the user selects a menu option the 1377# tag for that item is printed to stderr. 1378# 1379# This function allows you to dereference the tag chosen by the user back into 1380# the item associated with said tag. 1381# 1382# Pass the tag chosen by the user as the first argument, followed by the 1383# ordered list of tag/item pairs (HINT: use the same tag/item list as was 1384# passed to dialog(1) for consistency). 1385# 1386# If the tag cannot be found, NULL is returned. 1387# 1388f_dialog_menutag2item() 1389{ 1390 local tag="$1" tagn item 1391 shift 1 # tag 1392 1393 while [ $# -gt 0 ]; do 1394 tagn="$1" 1395 item="$2" 1396 shift 2 # tagn/item 1397 1398 if [ "$tag" = "$tagn" ]; then 1399 echo "$item" 1400 return $SUCCESS 1401 fi 1402 done 1403 return $FAILURE 1404} 1405 1406# f_dialog_menutag2item_with_help $tag_chosen $tag1 $item1 $help1 \ 1407# $tag2 $item2 $help2 ... 1408# 1409# To use the `--menu' option of dialog(1) with the `--item-help' option, you 1410# must pass an ordered list of tag/item/help triplets on the command-line. When 1411# the user selects a menu option the tag for that item is printed to stderr. 1412# 1413# This function allows you to dereference the tag chosen by the user back into 1414# the item associated with said tag (help is discarded/ignored). 1415# 1416# Pass the tag chosen by the user as the first argument, followed by the 1417# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list 1418# as was passed to dialog(1) for consistency). 1419# 1420# If the tag cannot be found, NULL is returned. 1421# 1422f_dialog_menutag2item_with_help() 1423{ 1424 local tag="$1" tagn item 1425 shift 1 # tag 1426 1427 while [ $# -gt 0 ]; do 1428 tagn="$1" 1429 item="$2" 1430 shift 3 # tagn/item/help 1431 1432 if [ "$tag" = "$tagn" ]; then 1433 echo "$item" 1434 return $SUCCESS 1435 fi 1436 done 1437 return $FAILURE 1438} 1439 1440# f_dialog_menutag2index $tag_chosen $tag1 $item1 $tag2 $item2 ... 1441# 1442# To use the `--menu' option of dialog(1) you must pass an ordered list of 1443# tag/item pairs on the command-line. When the user selects a menu option the 1444# tag for that item is printed to stderr. 1445# 1446# This function allows you to dereference the tag chosen by the user back into 1447# the index associated with said tag. The index is the one-based tag/item pair 1448# array position within the ordered list of tag/item pairs passed to dialog(1). 1449# 1450# Pass the tag chosen by the user as the first argument, followed by the 1451# ordered list of tag/item pairs (HINT: use the same tag/item list as was 1452# passed to dialog(1) for consistency). 1453# 1454# If the tag cannot be found, NULL is returned. 1455# 1456f_dialog_menutag2index() 1457{ 1458 local tag="$1" tagn n=1 1459 shift 1 # tag 1460 1461 while [ $# -gt 0 ]; do 1462 tagn="$1" 1463 shift 2 # tagn/item 1464 1465 if [ "$tag" = "$tagn" ]; then 1466 echo $n 1467 return $SUCCESS 1468 fi 1469 n=$(( $n + 1 )) 1470 done 1471 return $FAILURE 1472} 1473 1474# f_dialog_menutag2index_with_help $tag_chosen $tag1 $item1 $help1 \ 1475# $tag2 $item2 $help2 ... 1476# 1477# To use the `--menu' option of dialog(1) with the `--item-help' option, you 1478# must pass an ordered list of tag/item/help triplets on the command-line. When 1479# the user selects a menu option the tag for that item is printed to stderr. 1480# 1481# This function allows you to dereference the tag chosen by the user back into 1482# the index associated with said tag. The index is the one-based tag/item/help 1483# triplet array position within the ordered list of tag/item/help triplets 1484# passed to dialog(1). 1485# 1486# Pass the tag chosen by the user as the first argument, followed by the 1487# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list 1488# as was passed to dialog(1) for consistency). 1489# 1490# If the tag cannot be found, NULL is returned. 1491# 1492f_dialog_menutag2index_with_help() 1493{ 1494 local tag="$1" tagn n=1 1495 shift 1 # tag 1496 1497 while [ $# -gt 0 ]; do 1498 tagn="$1" 1499 shift 3 # tagn/item/help 1500 1501 if [ "$tag" = "$tagn" ]; then 1502 echo $n 1503 return $SUCCESS 1504 fi 1505 n=$(( $n + 1 )) 1506 done 1507 return $FAILURE 1508} 1509 1510############################################################ INIT FUNCTIONS 1511 1512# f_dialog_init 1513# 1514# Initialize (or re-initialize) the dialog module after setting/changing any 1515# of the following environment variables: 1516# 1517# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate 1518# that Xdialog(1) should be used instead of dialog(1). 1519# 1520# SECURE Either NULL or Non-NULL. If given a value will indicate 1521# that (while running as root) sudo(8) authentication is 1522# required to proceed. 1523# 1524f_dialog_init() 1525{ 1526 DIALOG_SELF_INITIALIZE= 1527 1528 # 1529 # Clone terminal stdout so we can redirect to it from within sub-shells 1530 # 1531 eval exec $DIALOG_TERMINAL_PASSTHRU_FD\>\&1 1532 1533 # 1534 # Add `-S' and `-X' to the list of standard arguments supported by all 1535 # 1536 case "$GETOPTS_STDARGS" in 1537 *SX*) : good ;; # already present 1538 *) GETOPTS_STDARGS="${GETOPTS_STDARGS}SX" 1539 esac 1540 1541 # 1542 # Process stored command-line arguments 1543 # 1544 f_dprintf "f_dialog_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \ 1545 "$ARGV" "$GETOPTS_STDARGS" 1546 SECURE=$( set -- $ARGV 1547 while getopts "$GETOPTS_STDARGS" flag > /dev/null; do 1548 case "$flag" in 1549 S) echo 1;; 1550 \?) continue;; 1551 esac 1552 done 1553 ) 1554 USE_XDIALOG=$( set -- $ARGV 1555 while getopts $GETOPTS_STDARGS flag > /dev/null; do 1556 case "$flag" in 1557 S|X) echo 1;; 1558 \?) continue;; 1559 esac 1560 done 1561 ) 1562 f_dprintf "f_dialog_init: SECURE=[%s] USE_XDIALOG=[%s]" \ 1563 "$SECURE" "$USE_XDIALOG" 1564 1565 # 1566 # Process `-X' command-line option 1567 # 1568 [ "$USE_XDIALOG" ] && DIALOG=Xdialog 1569 1570 # 1571 # Sanity check, or die gracefully 1572 # 1573 if ! f_have $DIALOG; then 1574 unset USE_XDIALOG 1575 failed_dialog="$DIALOG" 1576 DIALOG=dialog 1577 f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$failed_dialog" 1578 fi 1579 1580 # 1581 # If we're already running as root but we got there by way of sudo(8) 1582 # and we have X11, we should merge the xauth(1) credentials from our 1583 # original user. 1584 # 1585 if [ "$USE_XDIALOG" ] && 1586 [ "$( id -u )" = "0" ] && 1587 [ "$SUDO_USER" -a "$DISPLAY" ] 1588 then 1589 if ! f_have xauth; then 1590 # Die gracefully, as we [likely] can't use Xdialog(1) 1591 unset USE_XDIALOG 1592 DIALOG=dialog 1593 f_die 1 "$msg_no_such_file_or_directory" "$pgm" "xauth" 1594 fi 1595 HOSTNAME=$(hostname) 1596 displaynum="${DISPLAY#*:}" 1597 eval xauth -if \~$SUDO_USER/.Xauthority extract - \ 1598 \"\$HOSTNAME/unix:\$displaynum\" \ 1599 \"\$HOSTNAME:\$displaynum\" | sudo sh -c 'xauth -ivf \ 1600 ~root/.Xauthority merge - > /dev/null 2>&1' 1601 fi 1602 1603 # 1604 # Probe Xdialog(1) for maximum height/width constraints, or die 1605 # gracefully 1606 # 1607 if [ "$USE_XDIALOG" ]; then 1608 if ! maxsize=$( LANG= LC_ALL= $DIALOG --print-maxsize 2>&1 ) 1609 then 1610 # Xdialog(1) failed, fall back to dialog(1) 1611 unset USE_XDIALOG 1612 size=$( f_dialog_buttonbox_size "$DIALOG_TITLE" \ 1613 "$DIALOG_BACKTITLE" \ 1614 "$maxsize" "" ) 1615 eval dialog \ 1616 --title \"\$DIALOG_TITLE\" \ 1617 --backtitle \"\$DIALOG_BACKTITLE\" \ 1618 --ok-label \"\$msg_ok\" \ 1619 --msgbox \"\$maxsize\" $size 1620 exit $FAILURE 1621 fi 1622 1623 XDIALOG_MAXSIZE=$( 1624 set -- ${maxsize##*:} 1625 1626 height=${1%,} 1627 width=$2 1628 1629 echo $height $width 1630 ) 1631 unset maxsize 1632 fi 1633 1634 # 1635 # If using Xdialog(1), swap DIALOG_TITLE with DIALOG_BACKTITLE. 1636 # The reason for this is because many dialog(1) applications use 1637 # --backtitle for the program name (which is better suited as 1638 # --title with Xdialog(1)). 1639 # 1640 if [ "$USE_XDIALOG" ]; then 1641 _DIALOG_TITLE="$DIALOG_TITLE" 1642 DIALOG_TITLE="$DIALOG_BACKTITLE" 1643 DIALOG_BACKTITLE="$_DIALOG_TITLE" 1644 unset _DIALOG_TITLE 1645 fi 1646 1647 f_dprintf "f_dialog_init: dialog(1) API initialized." 1648} 1649 1650############################################################ MAIN 1651 1652# 1653# Self-initialize unless requested otherwise 1654# 1655f_dprintf "%s: DIALOG_SELF_INITIALIZE=[%s]" \ 1656 dialog.subr "$DIALOG_SELF_INITIALIZE" 1657case "$DIALOG_SELF_INITIALIZE" in 1658""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 1659*) f_dialog_init 1660esac 1661 1662f_dprintf "%s: Successfully loaded." dialog.subr 1663 1664fi # ! $_DIALOG_SUBR 1665