summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Hall <halex@cvs.openbsd.org>2009-06-09 10:11:22 +0000
committerAlexander Hall <halex@cvs.openbsd.org>2009-06-09 10:11:22 +0000
commit41c330fcb15102716299f143d3b37c38737ae4fb (patch)
tree337d33e0d181def51f3c951ec92035aab9ad71c6
parent74aa6f77bde55a52a48ea4fb3de9c232b8049cfd (diff)
Update the user input routines to (re-evaluate and) redraw the
question if dmesg changes are detected. The password reading routines are not subject to these changes at this point. ok deraadt@, krw@
-rw-r--r--distrib/miniroot/install.sh9
-rw-r--r--distrib/miniroot/install.sub146
2 files changed, 115 insertions, 40 deletions
diff --git a/distrib/miniroot/install.sh b/distrib/miniroot/install.sh
index a2634189bab..56b51c3f985 100644
--- a/distrib/miniroot/install.sh
+++ b/distrib/miniroot/install.sh
@@ -1,5 +1,5 @@
#!/bin/ksh
-# $OpenBSD: install.sh,v 1.200 2009/06/03 00:30:31 krw Exp $
+# $OpenBSD: install.sh,v 1.201 2009/06/09 10:11:21 halex Exp $
# $NetBSD: install.sh,v 1.5.2.8 1996/08/27 18:15:05 gwr Exp $
#
# Copyright (c) 1997-2009 Todd Miller, Theo de Raadt, Ken Westerback
@@ -65,12 +65,14 @@ MODE=install
cd /tmp
DISK=
+DISKS_DONE=
_DKDEVS=$(get_dkdevs)
# Remove traces of previous install attempt.
rm -f /tmp/fstab.shadow /tmp/fstab /tmp/fstab.*
while :; do
+ DISKS_DONE=$(addel "$DISK" $DISKS_DONE)
_DKDEVS=$(rmel "$DISK" $_DKDEVS)
# Always do ROOTDISK first, and repeat until it is configured.
@@ -82,7 +84,10 @@ while :; do
else
# Force the user to think and type in a disk name by
# making 'done' the default choice.
- ask_which "disk" "do you wish to initialize" "$_DKDEVS" done
+ ask_which "disk" "do you wish to initialize" \
+ '$(l=$(get_dkdevs); for a in $DISKS_DONE; do
+ l=$(rmel $a $l); done; bsort $l)' \
+ done
[[ $resp == done ]] && break
fi
diff --git a/distrib/miniroot/install.sub b/distrib/miniroot/install.sub
index 44f10d1ff7f..ecf2b4df09d 100644
--- a/distrib/miniroot/install.sub
+++ b/distrib/miniroot/install.sub
@@ -1,4 +1,4 @@
-# $OpenBSD: install.sub,v 1.576 2009/06/09 03:33:49 krw Exp $
+# $OpenBSD: install.sub,v 1.577 2009/06/09 10:11:21 halex Exp $
# $NetBSD: install.sub,v 1.5.2.8 1996/09/02 23:25:02 pk Exp $
#
# Copyright (c) 1997-2009 Todd Miller, Theo de Raadt, Ken Westerback
@@ -132,7 +132,7 @@ get_ifdevs() {
}
get_drive() {
- ask_which "$1" "contains the $MODE media" "$2"
+ ask_which "$1" "contains the $MODE media" "$2" "$3"
[[ $resp == done ]] && return 1
makedev $resp || return 1
return 0
@@ -157,7 +157,11 @@ mount_mnt2() {
else
# Display partitions with filesystems and ask which to use.
cat /tmp/parts.$_dev
- ask_which "$_dev partition" "has the $MODE sets" "$_parts"
+ ask_which "$_dev partition" "has the $MODE sets" \
+ '$(disklabel '$_dev' 2>/dev/null | grep "^ [a-p]: " |
+ egrep -v "swap|unused" |
+ sed '\''s/^ \(.\): .*/\1/'\'')'
+
[[ $resp == done ]] && return 1
fi
@@ -180,6 +184,77 @@ askpass() {
echo
}
+# Make sure lock is initially released
+rm -df /tmp/lock
+
+# Acquire lock
+lock() {
+ while ! mkdir /tmp/lock 2>&- && sleep .1; do done
+}
+
+# Release lock
+unlock() {
+ rm -d /tmp/lock 2>&-
+}
+
+# Add trap to kill the listener process
+retrap() {
+ trap '>&- && kill -KILL $cppid 2>&-; exit' INT EXIT TERM
+}
+
+# The dmesg listener will check for the existance of this file and send a
+# signal to the child process if the dmesg output differs from the contents
+# of that file
+rm -f /tmp/update
+
+# Start listener process looking for dmesg changes
+(
+ while :; do
+ lock
+ if test -e /tmp/update && [[ "`dmesg`" != "`cat /tmp/update`" ]]; then
+ dmesg >/tmp/update
+ kill -TERM 2>&- $$ || exit 1
+ fi
+ unlock
+ sleep .5
+ done
+) |&
+cppid=$!
+
+# Kill the child on exit
+retrap
+
+# Issue a read into the global variable $resp. If the dmesg output is
+# changed while inside this function, the current read will be aborted
+# and the function will return a non-zero value. Normally, the caller
+# will then reprint any prompt and call the function again.
+_ask() {
+ local _int _redo=0 _pid
+
+ trap "_int=1" INT
+ trap "_redo=1" TERM
+ lock; dmesg >/tmp/update; unlock
+ read resp
+ lock; rm /tmp/update; unlock
+ if (( _redo )); then
+ stty raw
+ stty -raw
+ else
+ case $resp in
+ !) echo "Type 'exit' to return to install."
+ sh
+ _redo=1
+ ;;
+ !*) eval "${resp#?}"
+ _redo=1
+ ;;
+ esac
+ fi
+ retrap
+ (( _int )) && kill -INT $$
+ return $_redo
+}
+
# Ask for user input.
#
# $1 = the question to ask the user
@@ -192,23 +267,11 @@ askpass() {
ask() {
local _question=$1 _default=$2
- set -o noglob
while :; do
echo -n "$_question "
[[ -z $_default ]] || echo -n "[$_default] "
- read resp
- case $resp in
- !) echo "Type 'exit' to return to install."
- sh
- ;;
- !*) eval "${resp#?}"
- ;;
- *) : ${resp:=$_default}
- break
- ;;
- esac
+ _ask && : ${resp:=$_default} && break
done
- set +o noglob
}
# Ask for a password twice, saving the input in $_password
@@ -308,29 +371,37 @@ ask_yn() {
# $3 = list of valid choices
# $4 = default choice, if it is not specified use the first item in $3
#
+# N.B.! $3 and $4 will be "expanded" using eval, so be sure to escape them
+# if they contain spooky stuff
+#
# At exit $resp holds selected item, or 'done'
ask_which() {
- local _name=$1 _query=$2 _list=$3 _def=$4
-
- set -- $_list
- if (( $# < 1 )); then
- resp=done
- return
- fi
- : ${_def:=$1}
-
- # Eliminate extraneous (especially trailing) whitespace in _list.
- _list="$*"
+ local _name=$1 _query=$2 _list=$3 _def=$4 _dynlist _dyndef
while :; do
# Put both lines in ask prompt, rather than use a
# separate 'echo' to ensure the entire question is
# re-ask'ed after a '!' or '!foo' shell escape.
- ask "Available ${_name}s are: $_list.\nWhich one $_query? (or 'done')" "$_def"
+ eval "_dynlist=\"$_list\""
+ eval "_dyndef=\"$_def\""
+
+ # Clean away whitespace and determine the default
+ set -o noglob
+ set -- $_dyndef; _dyndef="$1"
+ set -- $_dynlist; _dynlist="$*"
+ set +o noglob
+ (( $# < 1 )) && resp=done && return
+
+ : ${_dyndef:=$1}
+ echo "Available ${_name}s are: $_dynlist."
+ echo -n "Which one $_query? (or 'done') "
+ [[ -n $_dyndef ]] && echo -n "[$_dyndef] "
+ _ask || continue
+ [[ -z $resp ]] && resp="$_dyndef"
# Quote $resp to prevent user from confusing isin() by
# entering something like 'a a'.
- isin "$resp" $_list done && break
+ isin "$resp" $_dynlist done && break
echo "'$resp' is not a valid choice."
done
}
@@ -493,15 +564,12 @@ __EOT
configure_ifs() {
local _first _ifdevs _ifs _name _hn _vl=0 _vd _vi _p _tags
- # Select the initial default interface.
- _p=$(ifconfig netboot 2>/dev/null | sed -n '1s/:.*//p')
-
while :; do
# Create new vlan if possible.
ifconfig vlan$_vl create >/dev/null 2>&1
- _ifdevs=$(get_ifdevs)
ask_which "network interface" "do you wish to configure" \
- "$_ifdevs" "$_p"
+ '$(get_ifdevs)' \
+ ${_p:-'$( (ifconfig netboot 2>/dev/null | sed -n '\''1s/:.*//p'\''; get_ifdevs) | sed q )'}
[[ $resp == done ]] && break
_ifs=$resp
@@ -525,6 +593,7 @@ configure_ifs() {
! isin "$_vi" $_tags && break
done
fi
+ _ifdevs=$(get_ifdevs)
set -- $_ifdevs
while [[ $1 == vlan[0-9]* ]]; do
shift
@@ -1215,7 +1284,7 @@ install_mounted_fs() {
}
install_cdrom() {
- get_drive "CD-ROM" "$(get_cddevs)" || return
+ get_drive "CD-ROM" '$(get_cddevs)' || return
mount_mnt2 $resp || return
install_mounted_fs
@@ -1224,7 +1293,8 @@ install_cdrom() {
install_disk() {
ask_yn "Is the disk partition already mounted?"
if [[ $resp == n ]]; then
- get_drive "disk" "$(get_dkdevs)" || return
+ get_drive "disk" '$(bsort $(get_dkdevs))' \
+ '$(bsort $(rmel $ROOTDISK $(get_dkdevs)))' || return
mount_mnt2 $resp || return
fi
@@ -1256,7 +1326,7 @@ install_tape() {
local _z _bs
# Get the name of the tape device.
- get_drive "tape drive" "$MTDEVS" || return
+ get_drive "tape drive" '$MTDEVS' || return
export TAPE=/dev/nr$resp
if [[ ! -c $TAPE ]]; then
echo "$TAPE is not a character special file."
@@ -1856,7 +1926,7 @@ fi
# Get ROOTDISK, ROOTDEV and SWAPDEV.
[[ -n $(get_dkdevs) ]] || { echo "No disks found." ; exit ; }
-ask_which "disk" "is the root disk" "$(get_dkdevs)"
+ask_which "disk" "is the root disk" '$(get_dkdevs)'
[[ $resp == done ]] && exit
makedev $resp || exit