From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Tue, 26 Oct 2021 20:58:38 +0200 From: Alexey Gladkov To: make-initrd@lists.altlinux.org Message-ID: <20211026185838.mnkahrx2v4ja34hf@example.org> References: <20211024172254.5CD94A5E20@lists.altlinux.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20211024172254.5CD94A5E20@lists.altlinux.org> Subject: Re: [make-initrd] [PATCH v6 18/22] bootchain-interactive: initial feature X-BeenThere: make-initrd@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: make-initrd@lists.altlinux.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Oct 2021 18:58:40 -0000 Archived-At: List-Archive: On Sun, Oct 24, 2021 at 08:22:54PM +0300, Leonid Krivoshein wrote: > This feature adds the ability to use text dialogs in > the initramfs scripts. See README.md for more details. > > Signed-off-by: Leonid Krivoshein > --- > features/bootchain-interactive/README.md | 184 +++++++++++++ > features/bootchain-interactive/config.mk | 5 + > .../data/bin/activate-interactive-vt | 27 ++ > .../data/bin/interactive-sh-functions | 247 ++++++++++++++++++ > .../initrd/cmdline.d/bootchain-interactive | 3 + > .../data/lib/IM-widgets/choice | 60 +++++ > .../data/lib/IM-widgets/dlgmsg | 25 ++ > .../data/lib/IM-widgets/errmsg | 29 ++ > .../data/lib/IM-widgets/form | 70 +++++ > .../data/lib/IM-widgets/gauge | 31 +++ > .../data/lib/IM-widgets/ponder | 67 +++++ > features/bootchain-interactive/rules.mk | 2 + > 12 files changed, 750 insertions(+) > create mode 100644 features/bootchain-interactive/README.md > create mode 100644 features/bootchain-interactive/config.mk > create mode 100755 features/bootchain-interactive/data/bin/activate-interactive-vt > create mode 100644 features/bootchain-interactive/data/bin/interactive-sh-functions > create mode 100644 features/bootchain-interactive/data/etc/initrd/cmdline.d/bootchain-interactive > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/choice > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/dlgmsg > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/errmsg > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/form > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/gauge > create mode 100644 features/bootchain-interactive/data/lib/IM-widgets/ponder > create mode 100644 features/bootchain-interactive/rules.mk > > diff --git a/features/bootchain-interactive/README.md b/features/bootchain-interactive/README.md > new file mode 100644 > index 0000000..adb3de5 > --- /dev/null > +++ b/features/bootchain-interactive/README.md > @@ -0,0 +1,184 @@ > +# Feature: bootchain-interactive > + > +Feature adds the ability to use text dialogs in the initramfs scripts. > + > +## Boot parameters > + > +- `console=...` - Disable to switch TTY's, it useful for network/serial console. > +- `noaskuser` - Disable all dialogs, it useful for console without user. > +- `nolines` - Disable pseudo-graphics line drawing, it useful if not supported. > + > +## Synopsis > +``` > +. interactive-sh-functions > +``` > + > +## Global variables > + > +- `$IM_BACKTITLE` - Back title for all input and output dialogs. > +- `$IM_WIDGET_ARGS` - Additional arguments for `dialog` command. > +- `$CONSOLE` - Non-empty value, if switching between TTY's are disabled. > +- `$NOASKUSER` - Non-empty value, if all dialogs are disabled. > +- `$NOLINES` - Non-empty value, if pseudo-graphics line drawing are disabled. > + > +## Briefly API > + > +- `IM_is_active()` - Returns 0, if interactive mode already activated. > +- `IM_exec()` - Re-execute specified process on the foreground (tty2 by > + default). > +- `IM_activate()` - Request to immediately or delayed activation of the > + interactive mode. > +- `IM_load_widgets()` - Load specified widgets from the library. > +- `IM_load_all()` - Load all available widgets from the library. > +- `IM_start_output()` - Notify `interactive` feature about starting output. > +- `IM_start_input()` - Notify `interactive` feature about starting intput. > +- `IM_show_bootsplash()` - Show bootsplash such as plymoth and start the > + progress bar. > +- `IM_hide_bootsplash()` - Hide bootsplash such as plymoth and stop the > + progress bar. > +- `IM_update_bootsplash()` - Notify bootsplash such as plymoth about boot > + state changes. > + > +## Widgets library > + > +Library is a scripts set, located in /lib/IM-widgets directory inside intitramfs > +iamge. The base set can be extended. Before use input widgets, `IM_start_input()` > +must be called, and `IM_start_output()` in otherwise. > + > +### choice (input) > + > +Display menu with one or more items, labels before items not displayed. > +On success returns 0 and write choosen label to specified variable. Based > +on `dialog --menu`. > + > +Syntax: > +``` > +IM_choice [ ???] > +``` > + > +Example: > +``` > +text="Please choose the installation method." > + > +while ! IM_choice method "$text" \ > + nfs "NFS server" \ > + ftp "FTP server" \ > + http "HTTP server" \ > + cifs "SAMBA server" \ > + cdrom "CD-ROM Drive" \ > + disk "Hard Disk Drive" \ > + # > +do > + sleep 0.5 > +done > + > +case "$method" in > +nfs) > +??? > +esac > +``` > + > +### dlgmsg (input) > + > +Display text message. Always returns 0. Based on `dialog --msgbox`. > + > +Syntax: > +``` > +IM_dlgmsg <text> > +``` > + > +Example: > +``` > +IM_dlgmsg "Live is success!" "$text" > +``` > + > +### errmsg (input) > + > +Display error message. Always returns 0. Based on `dialog --msgbox`. > + > +Syntax: > +``` > +IM_errmsg <text> > +``` > + > +Example: > +``` > +IM_errmsg "Disk read error, try again!" > +``` > + > +### form (input) > + > +Display mixed data form. Input one or more text fields and store values > +to specified varibales. Some variables associated with private data, > +such as password, this input field characters outputs as asterics (`*`). > +On success returns 0 and fill all variables by the entered values. > +Based on `dialog --mixedform`. > + > +Syntax: > +``` > +IM_form <title> <text> <text-height> \ > + <varname1> <fldlen1> <caption1> \ > + [<varname2> <fldlen2> <caption2>???] > +``` > + > +Example: > +``` > +IM_form "$title" "$text" 5 \ > + server 64 "HTTP-server" \ > + directory 128 "Directory" \ > + || > + continue > +[ -n "$server" ] && [ -n "$directory" ] || > + continue > +``` > + > +### gauge (output) > + > +Display gauge (progress bar). Integer value from 0 to 100 must be sent > +via stdin to specify displayed percent of the process passed. This is work > +in conjuction with pv command. Always returns 0. Based on `dialog --gauge`. > + > +Note for `netconsole` usage: after process will finish, don't forget reset > +the terminal, otherwise keyboard input will be lost. > + > +Syntax: > +``` > +echo <integer> | IM_gauge <title> [<text>] > +``` > + > +Example: > +``` > +( for i in $(seq 1 10); do > + echo "${i}0" > + sleep 1 > + done > +) | IM_gauge "[ Loading... ]" > + > +[ -z "$CONSOLE" ] || > + reset > +``` > + > +### ponder (output) > + > +Displays the <waiting???> widget, which displays the undefined time of the > +ongoing process, works independently of the main program code. The parameters > +<delay> and <step> at startup determine by how many percent the thermometer > +will automatically advance after a given time, i.e. set the frequency and > +speed of the widget refresh. Always returns 0. Based on the `gauge` widget. > + > +Syntax: > +``` > +IM_ponder_start <title> [[[<text>] <delay>] <step>] > +??? > +IM_ponder_stop > +``` > + > +Example: > +``` > +IM_ponder_start "[ Scanning disk... ]" \ > + "Searching random bits on the disk for fill CRNG entropy..." > +find / -type f -print0 | > + xargs -0 grep "Linus Torvalds" >/tmp/Linus.txt 2>/dev/null > +rm -f /tmp/Linus.txt > +IM_ponder_stop > +``` > diff --git a/features/bootchain-interactive/config.mk b/features/bootchain-interactive/config.mk > new file mode 100644 > index 0000000..69c8756 > --- /dev/null > +++ b/features/bootchain-interactive/config.mk > @@ -0,0 +1,5 @@ > +$(call feature-requires,depmod-image) > + > +BOOTCHAIN_INTERACTIVE_DATADIR = $(FEATURESDIR)/bootchain-interactive/data > + > +BOOTCHAIN_INTERACTIVE_PROGS = chvt dialog openvt pv > diff --git a/features/bootchain-interactive/data/bin/activate-interactive-vt b/features/bootchain-interactive/data/bin/activate-interactive-vt > new file mode 100755 > index 0000000..90ae329 > --- /dev/null > +++ b/features/bootchain-interactive/data/bin/activate-interactive-vt > @@ -0,0 +1,27 @@ > +#!/bin/bash -efu > + > +. interactive-sh-functions > + > +delay="${1-}" > + > +IM_is_active || > + fatal "interactive mode required" > +exec </dev/null >/dev/null 2>&1 > + > +if [ -n "$delay" ]; then > + while [ ! -f "${_IM_activated}" ]; do > + [ "$delay" -gt 0 ] || > + break > + delay=$(( $delay - 1 )) > + sleep 1 > + done > + sleep 1 > +fi > + > +if [ ! -f "${_IM_activated}" ] && IM_is_active; then > + :> "${_IM_activated}" > + IM_hide_bootsplash > + [ -n "$CONSOLE" ] || > + chvt "${_IM_VT_number}" > + rootdelay_pause > +fi > diff --git a/features/bootchain-interactive/data/bin/interactive-sh-functions b/features/bootchain-interactive/data/bin/interactive-sh-functions > new file mode 100644 > index 0000000..9baf3df > --- /dev/null > +++ b/features/bootchain-interactive/data/bin/interactive-sh-functions > @@ -0,0 +1,247 @@ > +#!/bin/bash -efu > + > +if [ -z "${__interactive_sh_functions-}" ]; then > +__interactive_sh_functions=1 > + > +. /.initrd/initenv > +. initrd-sh-functions > + > +. shell-signal > + > +message_time=1 > + > +# Public > +IM_BACKTITLE= > +IM_WIDGET_ARGS= > +CONSOLE="${CONSOLE-}" > +NOASKUSER="${NOASKUSER-}" > +NOLINES="${NOLINES-}" > + > +# Internal > +_IM_max_width= > +_IM_widgetsdir=/lib/IM-widgets > +_IM_flag=/.initrd/interactive-mode > +_IM_unsplashed="${_IM_flag}/BOOTSPLASH-STOPPED" > +_IM_activated="${_IM_flag}/VT-ACTIVATED" > +_IM_VT_number="${_IM_VT_number:-2}" > + > +# Standart "reboot message" > +IM_RBMSG="Press ENTER to reboot the computer..." > + > + > +IM_is_active() > +{ > + [ -d "${_IM_flag}" ] || > + return 1 > +} > + > +IM_ponder_stop() > +{ > + : # Base implementation overrided in /lib/IM-widgets/ponder > +} > + > +_IM_exit_handler() > +{ > + local rc=$? > + > + trap - EXIT > + > + if IM_is_active; then > + IM_ponder_stop > + rootdelay_unpause > + if [ -z "$CONSOLE" ] && [ -z "$NOASKUSER" ]; then > + clear > + chvt 1 > + fi > + IM_show_bootsplash > + rm -rf -- "${_IM_flag}" > + fi > + > + exit $rc > +} > + > +IM_exec() > +{ > + local now= > + > + if [ "${1-}" = "--now" ]; then > + now=-s > + shift > + fi > + > + ! IM_is_active || > + fatal "already in interactive mode" > + > + if [ -n "$CONSOLE" ] || [ -n "$NOASKUSER" ]; then > + exec "$@" > + else > + [ -e "/dev/tty${_IM_VT_number}" ] || > + mknod "/dev/tty${_IM_VT_number}" c 4 ${_IM_VT_number} > + exec openvt -f -w $now -c${_IM_VT_number} -- "$@" > + fi > + > + fatal "exec failed in IM_exec()" > +} > + > +# shellcheck disable=SC2120 > +IM_activate() > +{ > + local delay="${1-}" > + local logfile="${2:-/var/log/IM.log}" > + > + ! IM_is_active || > + fatal "already in interactive mode" > + set_cleanup_handler _IM_exit_handler > + > + if [ -n "$NOASKUSER" ]; then > + exec </dev/null >/dev/null 2>>"$logfile" > + elif [ -n "$CONSOLE" ]; then > + exec </dev/console >/dev/console 2>>"$logfile" > + else > + exec <"/dev/tty${_IM_VT_number}" >"/dev/tty${_IM_VT_number}" 2>>"$logfile" > + fi > + > + mkdir -p -- "${_IM_flag}" > + > + export TERM="${TERM:-linux}" > + export DIALOG_TTY=1 > + export LC_ALL=C > + export LANG=C > + > + # Determinating maximum width > + if [ -n "$NOASKUSER" ]; then > + _IM_max_width=80 > + printf '%s\n' "${_IM_max_width}" >"${_IM_flag}/MAX-WIDTH" > + elif [ -z "${_IM_max_width}" ]; then > + local esc cols rows > + > + # The snippet above by Oleg Nesterov (C) was modified for IM, see: > + # https://lists.altlinux.org/pipermail/make-initrd/2021-June/000458.html > + # > + echo -ne "\e[s\e[1000;1000H\e[6n\e[u" > + # shellcheck disable=SC2162 > + IFS=';[' read -s -t2 -dR esc rows cols || { > + rows=24 > + cols=80 > + } > + _IM_max_width=$(( $cols - 6 )) > + stty rows "$rows" cols "$cols" 2>/dev/null ||: > + printf '%s\n' "${_IM_max_width}" >"${_IM_flag}/MAX-WIDTH" > + fi > + > + # Activating IM VT > + if [ -n "$NOASKUSER" ]; then > + message "TTY's not used, dialogs are disabled" > + elif [ -n "$CONSOLE" ]; then > + activate-interactive-vt > + message "TTY's not available, using current system console" > + elif [ -z "$delay" ]; then > + activate-interactive-vt > + message "TTY${_IM_VT_number} now active" > + else > + activate-interactive-vt "$delay" & > + message "TTY${_IM_VT_number} will be activated after $((1 + $delay)) seconds" > + fi > + > + # Warm up: back title do not displayed only with the first widget > + # after openvt(), single dialog exec strangely solve this problem. > + # > + if [ -z "$CONSOLE" ] && [ -z "$NOASKUSER" ]; then > + dialog ${NOLINES:+--ascii-lines} \ > + --backtitle "WARM UP" \ > + --title "[ Loading widgets ]" \ > + --pause "" 7 40 0 \ > + ||: > + fi > + > + # Also we need to load and to check all widgets before using them > + IM_load_all > +} > + > +IM_load_widgets() > +{ > + local widget loaded > + > + for widget in "$@" _; do > + [ -s "${_IM_widgetsdir}/$widget" ] || > + continue > + eval "loaded=\"\${__IM_${widget}_loaded-}\"" > + > + if [ -z "$loaded" ]; then > + eval "__IM_${widget}_loaded=1" > + . "${_IM_widgetsdir}/$widget" > + fi > + done > +} > + > +IM_load_all() > +{ > + local widget > + > + # shellcheck disable=SC2045 > + for widget in $(ls -- "${_IM_widgetsdir}/"); do > + IM_load_widgets "$widget" > + done > +} > + > +IM_start_output() > +{ > + # shellcheck disable=SC2119 > + IM_is_active || > + IM_activate > + [ -n "${_IM_max_width}" ] || > + read -r _IM_max_width <"${_IM_flag}/MAX-WIDTH" || > + _IM_max_width=66 > + IM_load_widgets "$@" > +} > + > +IM_start_input() > +{ > + [ -z "$NOASKUSER" ] || > + fatal "input widgets not allowed, dialogs are disabled" > + IM_start_output "$@" > + [ -f "${_IM_activated}" ] || > + activate-interactive-vt > +} > + > +IM_show_bootsplash() > +{ > + local cmd=plymouth > + > + if IM_is_active && > + [ -f "${_IM_unsplashed}" ] && > + command -v $cmd >/dev/null && > + $cmd --ping >/dev/null 2>&1 > + then > + $cmd unpause-progress --show-splash ||: > + rm -f -- "${_IM_unsplashed}" > + fi > +} > + > +IM_hide_bootsplash() > +{ > + local cmd=plymouth > + > + if IM_is_active && > + [ ! -f "${_IM_unsplashed}" ] && > + command -v $cmd >/dev/null && > + $cmd --ping >/dev/null 2>&1 > + then > + $cmd pause-progress --hide-splash ||: > + :> "${_IM_unsplashed}" > + fi > +} > + > +IM_update_bootsplash() > +{ > + local cmd=plymouth > + > + if IM_is_active && > + command -v $cmd >/dev/null && > + $cmd --ping >/dev/null 2>&1 > + then > + $cmd update --status="$1" ||: > + fi > +} > + > +fi # __interactive_sh_functions > diff --git a/features/bootchain-interactive/data/etc/initrd/cmdline.d/bootchain-interactive b/features/bootchain-interactive/data/etc/initrd/cmdline.d/bootchain-interactive > new file mode 100644 > index 0000000..8676770 > --- /dev/null > +++ b/features/bootchain-interactive/data/etc/initrd/cmdline.d/bootchain-interactive > @@ -0,0 +1,3 @@ > +register_parameter string CONSOLE > +register_parameter bool NOASKUSER > +register_parameter bool NOLINES > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/choice b/features/bootchain-interactive/data/lib/IM-widgets/choice > new file mode 100644 > index 0000000..23517e0 > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/choice > @@ -0,0 +1,60 @@ > +#!/bin/bash -efu > + > +IM_choice() > +{ > + IM_start_input > + > + local varname="$1" text="${2:-\n}"; shift 2 > + local height=1 width=$(( 4 + ${#text} )) > + local rc=0 items=$(( $# / 2 )) > + > + _calculate_items_width() > + { > + local label iw i=0 > + > + while [ $i -lt $items ]; do > + label="$2"; shift 2 > + iw=$(( 4 + ${#label} )) > + [ $iw -le $width ] || > + width=$iw > + i=$((1 + $i)) > + done > + } > + > + [ $items -gt 0 ] || > + return 1 > + [ $width -gt "${_IM_max_width}" ] || > + _calculate_items_width "$@" > + if [ $width -lt 40 ]; then > + width=40 > + elif [ $width -gt ${_IM_max_width} ]; then > + height=$(( $width / ${_IM_max_width} + 1 )) > + width=${_IM_max_width} > + fi > + if [ $items -gt 7 ]; then > + height=$((14 + $height)) > + else > + height=$((7 + $height + $items)) > + fi > + > + local dlgcmd="dialog $IM_WIDGET_ARGS ${NOLINES:+--ascii-lines}" > + dlgcmd="$dlgcmd ${IM_BACKTITLE:+--backtitle \"$IM_BACKTITLE\"}" > + dlgcmd="$dlgcmd --title \"[ Please choose... ]\"" > + dlgcmd="$dlgcmd --no-tags --menu \"\n$text\"" > + dlgcmd="$dlgcmd $height $width $items" > + > + while [ $# -ge 2 ]; do > + dlgcmd="$dlgcmd \"$1\" \"$2\"" > + shift 2 > + done > + > + exec 3>&1 > + text="$(eval "$dlgcmd" 2>&1 1>&3)" || rc=$? Вот этим eval ты запросто можешь выполнить любой произвольный код из $text или другой переменной из аргументов. На самом деле тебе этот eval не нужен, если аккуратно заполнить свои же аргументы: set -- $IM_WIDGET_ARGS \ ${NOLINES:+--ascii-lines} \ ${IM_BACKTITLE:+--backtitle "$IM_BACKTITLE"} \ --title "[ Please choose... ]" \ --no-tags --menu "\n$text" \ $height $width $items \ "$@" text="$(dialog "$@" 2>&1 1>&3)" || rc=$? Ну а можно и как ниже вообще без set сразу dialog передавать аргументы. > + exec 3>&- > + > + [ -z "$CONSOLE" ] || > + reset > + [ $rc -eq 0 ] || > + return $rc > + eval "$varname=\"$text\"" eval "$varname=\"\$text\"" ^ > +} > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/dlgmsg b/features/bootchain-interactive/data/lib/IM-widgets/dlgmsg > new file mode 100644 > index 0000000..74e1eba > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/dlgmsg > @@ -0,0 +1,25 @@ > +#!/bin/bash -efu > + > +IM_dlgmsg() > +{ > + IM_start_input > + > + local title="$1" text="$2" height=2 > + local width=$(( 4 + ${#text} )) > + > + if [ $width -lt 40 ]; then > + width=40 > + elif [ $width -gt ${_IM_max_width} ]; then > + height=$(( $width / ${_IM_max_width} + 2 )) > + width=${_IM_max_width} > + fi > + > + dialog $IM_WIDGET_ARGS \ > + ${NOLINES:+--ascii-lines} \ > + ${IM_BACKTITLE:+--backtitle "$IM_BACKTITLE"} \ > + --title "$title" \ > + --msgbox "\n$text" \ > + $((4 + $height)) $width ||: > + [ -z "$CONSOLE" ] || > + reset > +} > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/errmsg b/features/bootchain-interactive/data/lib/IM-widgets/errmsg > new file mode 100644 > index 0000000..e5f05db > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/errmsg > @@ -0,0 +1,29 @@ > +#!/bin/bash -efu > + > +IM_errmsg() > +{ > + IM_start_input > + > + local text="$1" height=2 > + local width=$(( 4 + ${#text} )) > + > + if [ $width -lt 40 ]; then > + width=40 > + elif [ $width -gt ${_IM_max_width} ]; then > + height=$(( $width / ${_IM_max_width} + 2 )) > + width=${_IM_max_width} > + fi > + > + [ ! -s /etc/dialogrc.error ] || > + export DIALOGRC=/etc/dialogrc.error > + dialog $IM_WIDGET_ARGS \ > + ${NOLINES:+--ascii-lines} \ > + ${IM_BACKTITLE:+--backtitle "$IM_BACKTITLE"} \ > + --title "[ Error! ]" \ > + --msgbox "\n$text" \ > + $((4 + $height)) $width ||: > + [ -z "$CONSOLE" ] || > + reset > + [ ! -s /etc/dialogrc.error ] || > + export DIALOGRC= > +} > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/form b/features/bootchain-interactive/data/lib/IM-widgets/form > new file mode 100644 > index 0000000..0c8c98e > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/form > @@ -0,0 +1,70 @@ > +#!/bin/bash -efu > + > +IM_form() > +{ > + IM_start_input > + > + local i=0 lw=0 formHeight=$(( $# / 3 - 1 )) > + local title="$1" text="$2" textHeight="$3" > + local label varname ilen itype; shift 3 > + > + _calculate_labels_width() > + { > + while [ $i -lt $formHeight ]; do > + label="$3"; shift 3 > + [ ${#label} -le $lw ] || > + lw=${#label} > + i=$((1 + $i)) > + done > + } > + > + [ $formHeight -gt 0 ] || > + return 1 > + [ -n "$title" ] || > + title="[ Please fill entries... ]" > + _calculate_labels_width "$@" > + lw=$((4 + $lw)); i=1 > + > + local width=60 rc=0 vars="" values="" > + local height=$((7 + $textHeight + $formHeight)) > + local fieldWidth=$(( $width - $lw - 6 )) > + > + local dlgcmd="dialog $IM_WIDGET_ARGS ${NOLINES:+--ascii-lines}" > + dlgcmd="$dlgcmd ${IM_BACKTITLE:+--backtitle \"$IM_BACKTITLE\"}" > + dlgcmd="$dlgcmd --insecure --title \"$title\"" > + dlgcmd="$dlgcmd --mixedform \"\n$text\"" > + dlgcmd="$dlgcmd $height $width $formHeight" > + > + while [ $i -le $formHeight ]; do > + varname="$1" > + ilen="$2" > + label="$3" > + shift 3 > + itype=0 > + case "$varname" in > + password*|passwd*|pass|pass1|pass2) > + itype=1 > + ;; > + esac > + vars="${vars}${varname} " > + dlgcmd="$dlgcmd \"$label:\" $i 1 \"\${$varname}\"" > + dlgcmd="$dlgcmd $i $lw $fieldWidth $ilen $itype" > + i=$((1 + $i)) > + done > + > + exec 3>&1 > + values=$(eval "$dlgcmd" 2>&1 1>&3) || rc=$? Тоже самое что и в IM_choice. > + exec 3>&- > + > + [ -z "$CONSOLE" ] || > + reset > + [ "$rc" = 0 ] || > + return $rc > + i=1 > + while [ "$i" -le "$formHeight" ]; do > + varname="$(echo "$vars" |cut -f$i -d ' ')" > + rc="$(echo "$values" |sed -n -r ${i}p)" > + eval "$varname=\"$rc\"" eval "$varname=\"\$rc\"" ^ $ echo $HOME /home/legion $ text='$HOME' $ eval "v=\"$text\"" $ echo $v /home/legion $ eval "v=\"\$text\"" $ echo $v $HOME > + i=$((1 + $i)) > + done > +} > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/gauge b/features/bootchain-interactive/data/lib/IM-widgets/gauge > new file mode 100644 > index 0000000..baf7ac5 > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/gauge > @@ -0,0 +1,31 @@ > +#!/bin/bash -efu > + > +IM_gauge() > +{ > + IM_start_output > + > + local title="$1" text="${2-}" > + local height=1 width=$(( 4 + ${#text} )) > + > + if [ $width -gt ${_IM_max_width} ]; then > + height=$(( $width / ${_IM_max_width} + 1 )) > + width=${_IM_max_width} > + elif [ $width -lt 40 ]; then > + [ $width -ne 4 ] || > + height=0 > + width=40 > + fi > + > + if [ -n "$text" ]; then > + height=$((1 + $height)) > + text="\n$text" > + fi > + > + dialog $IM_WIDGET_ARGS \ > + ${NOLINES:+--ascii-lines} \ > + ${IM_BACKTITLE:+--backtitle "$IM_BACKTITLE"} \ > + --title "$title" \ > + --gauge "$text" \ > + $((5 + $height)) $width 2>/dev/null \ > + ||: > +} > diff --git a/features/bootchain-interactive/data/lib/IM-widgets/ponder b/features/bootchain-interactive/data/lib/IM-widgets/ponder > new file mode 100644 > index 0000000..c6d4600 > --- /dev/null > +++ b/features/bootchain-interactive/data/lib/IM-widgets/ponder > @@ -0,0 +1,67 @@ > +#!/bin/bash -efu > + > +# Internal > +_IM_ponder_pid= > +_IM_ponder_finished="${_IM_flag}/PONDER-FINISHED" > + > +_IM_ponder_bg() > +{ > + local dlgcmd="IM_gauge \"$1\" \"$2\"" > + local delay="$3" step="$4" percent=0 forward=1 > + > + ( while [ ! -f "${_IM_ponder_finished}" ]; do > + echo "$percent" > + > + if [ $forward -ne 0 ]; then > + if [ $percent -lt 100 ]; then > + percent=$(( $percent + $step )) > + else > + percent=$(( $percent - $step )) > + forward=0 > + fi > + else > + if [ $percent -gt 0 ]; then > + percent=$(( $percent - $step )) > + else > + percent=$(( $percent + $step )) > + forward=1 > + fi > + fi > + > + [ $percent -le 100 ] || > + percent=100 > + [ $percent -ge 0 ] || > + percent=0 > + sleep "$delay" > + done > + > + echo "100" > + ) |eval "$dlgcmd" А тут зачем eval если это IM_gauge "$1" "$2" ? > +} > + > +IM_ponder_start() > +{ > + IM_start_output gauge > + > + local title="$1" text="${2-}" > + local delay="${3:-0.5}" > + local step="${4:-10}" > + > + [ -z "${_IM_ponder_pid}" ] || > + return 0 > + rm -f -- "${_IM_ponder_finished}" > + _IM_ponder_bg "$title" "$text" "$delay" "$step" & > + _IM_ponder_pid=$! > +} > + > +IM_ponder_stop() > +{ > + [ -n "${_IM_ponder_pid}" ] || > + return 0 > + :> "${_IM_ponder_finished}" > + wait "${_IM_ponder_pid}" 2>/dev/null ||: > + rm -f -- "${_IM_ponder_finished}" > + [ -z "$CONSOLE" ] || > + reset > + _IM_ponder_pid= > +} > diff --git a/features/bootchain-interactive/rules.mk b/features/bootchain-interactive/rules.mk > new file mode 100644 > index 0000000..b647caf > --- /dev/null > +++ b/features/bootchain-interactive/rules.mk > @@ -0,0 +1,2 @@ > +PUT_FEATURE_DIRS += $(BOOTCHAIN_INTERACTIVE_DATADIR) > +PUT_FEATURE_PROGS += $(BOOTCHAIN_INTERACTIVE_PROGS) > -- > 2.24.1 > > _______________________________________________ > Make-initrd mailing list > Make-initrd@lists.altlinux.org > https://lists.altlinux.org/mailman/listinfo/make-initrd -- Rgrds, legion