Home | History | Annotate | Line # | Download | only in miniroot
install.sub revision 1.59
      1 #!/bin/sh
      2 #	$NetBSD: install.sub,v 1.59 2020/12/12 05:23:21 tsutsui Exp $
      3 #
      4 # Copyright (c) 1996 The NetBSD Foundation, Inc.
      5 # All rights reserved.
      6 #
      7 # This code is derived from software contributed to The NetBSD Foundation
      8 # by Jason R. Thorpe.
      9 #
     10 # Redistribution and use in source and binary forms, with or without
     11 # modification, are permitted provided that the following conditions
     12 # are met:
     13 # 1. Redistributions of source code must retain the above copyright
     14 #    notice, this list of conditions and the following disclaimer.
     15 # 2. Redistributions in binary form must reproduce the above copyright
     16 #    notice, this list of conditions and the following disclaimer in the
     17 #    documentation and/or other materials provided with the distribution.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29 # POSSIBILITY OF SUCH DAMAGE.
     30 #
     31 
     32 #	NetBSD installation/upgrade script - common subroutines.
     33 
     34 ROOTDISK=""				# filled in below
     35 MACHINE=				# filled by distrib/miniroot/list
     36 export MACHINE
     37 VERSION=100				# updated by distrib/miniroot/list
     38 export VERSION
     39 RELEASE=10.0				# updated by distrib/miniroot/list
     40 export RELEASE
     41 
     42 ALLSETS="base comp etc games man misc modules rescue text"	# default install sets
     43 UPGRSETS="base comp games man misc text"		# default upgrade sets
     44 THESETS=						# one of the above
     45 
     46 local_sets_dir=""			# Path searched for sets by install_sets
     47 					# on the local filesystems
     48 
     49 # decide upon an editor
     50 if [ -z "$EDITOR" ]; then
     51 	if [ -x /usr/bin/vi ]; then
     52 		EDITOR=vi
     53 	else
     54 		EDITOR=ed
     55 	fi
     56 fi
     57 
     58 getresp() {
     59 	read resp
     60 	if [ -z "$resp" ]; then
     61 		resp=$1
     62 	fi
     63 }
     64 
     65 isin() {
     66 # test the first argument against the remaining ones, return succes on a match
     67 	_a=$1; shift
     68 	while [ $# != 0 ]; do
     69 		if [ "$_a" = "$1" ]; then return 0; fi
     70 		shift
     71 	done
     72 	return 1
     73 }
     74 
     75 rmel() {
     76 # remove first argument from list formed by the remaining arguments
     77 	local	_a
     78 
     79 	_a=$1; shift
     80 	while [ $# != 0 ]; do
     81 		if [ "$_a" != "$1" ]; then
     82 			echo "$1";
     83 		fi
     84 		shift
     85 	done
     86 }
     87 
     88 cutword () {
     89 # read a line of data, return Nth element.
     90 	local _a
     91 	local _n
     92 	local _oifs
     93 
     94 	# optional field separator
     95 	_oifs="$IFS"
     96 	case "$1" in
     97 		-t?*) IFS=${1#-t}; shift;;
     98 	esac
     99 
    100 	_n=$1
    101 	read _a; set -- $_a
    102 	IFS="$_oifs"
    103 	if [ "$1" = "" ]; then return; fi
    104 	eval echo \$$_n
    105 }
    106 
    107 cutlast () {
    108 # read a line of data, return last element. Equiv. of awk '{print $NF}'.
    109 	local _a
    110 	local _oifs
    111 
    112 	# optional field separator
    113 	_oifs="$IFS"
    114 	case "$1" in
    115 		-t?*) IFS=${1#-t}; shift;;
    116 	esac
    117 
    118 	read _a; set -- $_a
    119 	IFS="$_oifs"
    120 	if [ "$1" = "" ]; then return; fi
    121 	eval echo '"${'"$#"'}"'
    122 }
    123 
    124 firstchar () {
    125 # return first character of argument
    126 	local _a
    127 	_a=$1
    128 	while [ ${#_a} != 1 ]; do
    129 		_a=${_a%?}
    130 	done
    131 	echo $_a
    132 }
    133 
    134 basename () {
    135 	local _oifs
    136 	if [ "$1" = "" ]; then return; fi
    137 	_oifs="$IFS"
    138 	IFS="/"
    139 	set -- $1
    140 	IFS="$_oifs"
    141 	eval echo '"${'"$#"'}"'
    142 }
    143 
    144 dir_has_sets() {
    145 	# return true when the directory $1 contains a set for $2...$n
    146 	local _dir
    147 	local _file
    148 
    149 	_dir=$1; shift
    150 	for _file in $*
    151 	do
    152 		if [ -f $_dir/${_file}.tar.gz ]; then
    153 			return 0
    154 		fi
    155 		# Try for stupid msdos convention
    156 		if [ -f $_dir/${_file}.tgz ]; then
    157 			return 0
    158 		fi
    159 		# Try for uncompressed files
    160 		if [ -f $_dir/${_file}.tar ]; then
    161 			return 0
    162 		fi
    163 		# Try for split files
    164 		if [ -f $_dir/${_file}${VERSION}.aa ]; then
    165 			return 0
    166 		fi
    167 	done
    168 	return 1
    169 }
    170 
    171 twiddle() {
    172 # spin the propeller so we don't get bored
    173 	while : ; do  
    174 		sleep 1; echo -n "/";
    175 		sleep 1; echo -n "-";
    176 		sleep 1; echo -n "\\";
    177 		sleep 1; echo -n "|";
    178 	done > /dev/tty & echo $!
    179 }
    180 
    181 get_localdir() {
    182 	# $1 is relative mountpoint
    183 	local _mp
    184 	local _dir
    185 
    186 	_mp=$1
    187 	_dir=
    188 	while : ; do
    189 	    if [ -n "$_mp" ]; then
    190 		cat << __get_localdir_1
    191 Note: your filesystems are mounted under the temporary mount point \"$_mp\".
    192 The pathname you are requested to enter below should NOT include the \"$_mp\"
    193 prefix.
    194 __get_localdir_1
    195 	    fi
    196 	    echo -n "Enter the pathname where the sets are stored [$_dir] "
    197 	    getresp "$_dir"
    198 	    _dir=$resp
    199 
    200 	    # Allow break-out with empty response
    201 	    if [ -z "$_dir" ]; then
    202 		echo -n "Are you sure you don't want to set the pathname? [n] "
    203 		getresp "n"
    204 		case "$resp" in
    205 			y*|Y*)
    206 				break
    207 				;;
    208 			*)
    209 				continue
    210 				;;
    211 		esac
    212 	    fi
    213 
    214 	    if dir_has_sets "$_mp/$_dir" $THESETS
    215 	    then
    216 		local_sets_dir="$_mp/$_dir"
    217 		break
    218 	    else
    219 		cat << __get_localdir_2
    220 The directory \"$_mp/$_dir\" does not exist, or does not hold any of the
    221 upgrade sets.
    222 __get_localdir_2
    223 		echo -n "Re-enter pathname? [y] "
    224 		getresp "y"
    225 		case "$resp" in
    226 			y*|Y*)
    227 				;;
    228 			*)
    229 				local_sets_dir=""
    230 				break
    231 				;;
    232 		esac
    233 	    fi
    234 	done
    235 }
    236 
    237 getrootdisk() {
    238 	cat << \__getrootdisk_1
    239 
    240 The installation program needs to know which disk to consider
    241 the root disk.  Note the unit number may be different than
    242 the unit number you used in the standalone installation
    243 program.
    244 
    245 Available disks are:
    246 
    247 __getrootdisk_1
    248 	_DKDEVS=$(md_get_diskdevs)
    249 	echo	"$_DKDEVS"
    250 	echo	""
    251 	echo -n	"Which disk is the root disk? "
    252 	getresp ""
    253 	if isin $resp $_DKDEVS ; then
    254 		ROOTDISK="$resp"
    255 	else
    256 		echo ""
    257 		echo "The disk $resp does not exist."
    258 		ROOTDISK=""
    259 	fi
    260 }
    261 
    262 labelmoredisks() {
    263 	cat << \__labelmoredisks_1
    264 
    265 You may label the following disks:
    266 
    267 __labelmoredisks_1
    268 	echo "$_DKDEVS"
    269 	echo	""
    270 	echo -n	"Label which disk? [done] "
    271 	getresp "done"
    272 	case "$resp" in
    273 		"done")
    274 			;;
    275 
    276 		*)
    277 			if isin $resp $_DKDEVS ; then
    278 				md_labeldisk $resp
    279 			else
    280 				echo ""
    281 				echo "The disk $resp does not exist."
    282 			fi
    283 			;;
    284 	esac
    285 }
    286 
    287 addhostent() {
    288 	# $1 - IP address
    289 	# $2 - symbolic name
    290 
    291 	local fqdn
    292 
    293 	# Create an entry in the hosts table.  If no host table
    294 	# exists, create one.  If the IP address already exists,
    295 	# replace its entry.
    296 	if [ ! -f /tmp/hosts ]; then
    297 		echo "127.0.0.1 localhost" > /tmp/hosts
    298 	fi
    299 
    300 	sed "/^$1 /d" < /tmp/hosts > /tmp/hosts.new
    301 	mv /tmp/hosts.new /tmp/hosts
    302 
    303 	if [ -n "${FQDN}" ]; then
    304 		fqdn=$2.$FQDN
    305 	fi
    306 	echo "$1 $2 $fqdn" >> /tmp/hosts
    307 }
    308 
    309 addifconfig() {
    310 	# $1 - interface name
    311 	# $2 - interface symbolic name
    312 	# $3 - interface IP address
    313 	# $4 - interface netmask
    314 	# $5 - (optional) interface link-layer medium, preceded by "media ", else ""
    315 	# $6 - (optional) interface link-layer directives
    316 	local _m
    317 
    318 	# Create a ifconfig.* file for the interface.
    319 	echo "inet $2 netmask $4 $5 $6" > /tmp/ifconfig.$1
    320 
    321 	addhostent $3 $2
    322 }
    323 
    324 configurenetwork() {
    325 	local _ifsdone
    326 	local _ifs
    327 
    328 #	_IFS=$(md_get_ifdevs)
    329 	_IFS=$(ifconfig -l | sed '
    330 		s/lo0//
    331 		s/ppp[0-9]//g
    332 		s/sl[0-9]//g
    333 		s/tun[0-9]//g')
    334 
    335 	_ifsdone=""
    336 	resp=""		# force at least one iteration
    337 	while [ "${resp}" != "done" ]; do
    338 	cat << \__configurenetwork_1
    339 
    340 You may configure the following network interfaces (the interfaces
    341 marked with [X] have been successfully configured):
    342 
    343 __configurenetwork_1
    344 
    345 		for _ifs in $_IFS; do
    346 			if isin $_ifs $_ifsdone ; then
    347 				echo -n "[X] "
    348 			else
    349 				echo -n "    "
    350 			fi
    351 			echo $_ifs
    352 		done
    353 		echo	""
    354 		echo -n	"Configure which interface? [done] "
    355 		getresp "done"
    356 		case "$resp" in
    357 		"done")
    358 			;;
    359 		*)
    360 			_ifs=$resp
    361 			if isin $_ifs $_IFS ; then
    362 				if configure_ifs $_ifs ; then
    363 					_ifsdone="$_ifs $_ifsdone"
    364 				fi
    365 			else
    366 				echo "Invalid response: \"$resp\" is not in list"
    367 			fi
    368 			;;
    369 		esac
    370 	done
    371 }
    372 
    373 configure_ifs() {
    374 
    375 	local _up
    376 	local _interface_name
    377 	local _interface_ip
    378 	local _interface_mask
    379 	local _interface_symname
    380 	local _interface_extra
    381 	local _interface_mediumtype
    382 	local _interface_supported_media
    383 	local _m
    384 	local _t
    385 
    386 	_interface_name=$1
    387 	_up=DOWN
    388 	if isin $_interface_name $(ifconfig -l -u); then
    389 		_up=UP
    390 	fi
    391 
    392 	_interface_supported_media=$(ifconfig -m $_interface_name | sed -n '
    393 		/^[ 	]*media autoselect/d
    394 		4,$s/[ 	]*media //p')
    395 
    396 	# get current "media" "ip" and "netmask" ("broadcast")
    397 	_t=$(ifconfig $_interface_name | sed -n '
    398 		s/^[ 	]*media: [^ 	]* \([^ ][^ ]*\).*/\1/p')
    399 
    400 	if [ "$_t" != "manual" ] && [ "$_t" != "media:" ] && [ "$_t" != "autoselect" ];
    401 	then
    402 		_interface_mediumtype=$1
    403 	fi
    404 
    405 	set -- $(ifconfig $_interface_name | sed -n '
    406 		/^[ 	]*inet/{
    407 		s/inet//
    408 		s/--> [0-9.][0-9.]*//
    409 		s/netmask//
    410 		s/broadcast//
    411 		p;}')
    412 
    413 	_interface_ip=$1
    414 	_interface_mask=$2
    415 
    416 	# Get IP address
    417 	resp=""		# force one iteration
    418 	while [ -z "${resp}" ]; do
    419 		echo -n "IP address? [$_interface_ip] "
    420 		getresp "$_interface_ip"
    421 		_interface_ip=$resp
    422 	done
    423 
    424 	# Get symbolic name
    425 	resp=""		# force one iteration
    426 	while [ -z "${resp}" ]; do
    427 		echo -n "Symbolic (host) name? "
    428 		getresp ""
    429 		_interface_symname=$resp
    430 	done
    431 
    432 	# Get netmask
    433 	resp=""		# force one iteration
    434 	while [ -z "${resp}" ]; do
    435 		echo -n "Netmask? [$_interface_mask] "
    436 		getresp "$_interface_mask"
    437 		_interface_mask=$resp
    438 	done
    439 
    440 	echo "Your network interface might require explicit selection"
    441 	echo "of the type of network medium attached. Supported media:"
    442 	echo "$_interface_supported_media"
    443 	echo -n "Additional media type arguments (none)? [$_interface_mediumtype] "
    444 	getresp "$_interface_mediumtype"
    445 	_m=""
    446 	if [ "${resp:-none}" != "none" ]; then
    447 		_interface_mediumtype=$resp
    448 		_m="media ${resp}"
    449 	fi
    450 
    451 
    452 	echo "Your network interface might require additional link-layer"
    453 	echo "directives (like 'link0'). If this is the case you can enter"
    454 	echo "these at the next prompt."
    455 	echo ""
    456 	echo -n "Additional link-layer arguments (none)? [$_interface_extra] "
    457 	getresp "$_interface_extra"
    458 	if [ "${resp:-none}" != "none" ]; then
    459 		_interface_extra=$resp
    460 	fi
    461 
    462 	# Configure the interface.  If it
    463 	# succeeds, add it to the permanent
    464 	# network configuration info.
    465 	if [ $_up != "UP" ]; then
    466 		ifconfig ${_interface_name} down
    467 		if ifconfig ${_interface_name} inet \
    468 		    ${_interface_ip} \
    469 		    netmask ${_interface_mask} \
    470 		    ${_interface_extra} ${_m} up ; then
    471 			addifconfig \
    472 			    "${_interface_name}" \
    473 			    "${_interface_symname}" \
    474 			    "${_interface_ip}" \
    475 			    "${_interface_mask}" \
    476 			    "${_m}" \
    477 			    "${_interface_extra}"
    478 			return 0
    479 		fi
    480 	else
    481 		echo "Interface ${_interface_name} is already active."
    482 		echo "Just saving configuration on new root filesystem."
    483 		addifconfig \
    484 		    "${_interface_name}" \
    485 		    "${_interface_symname}" \
    486 		    "${_interface_ip}" \
    487 		    "${_interface_mask}" \
    488 		    "${_m}" \
    489 		    "${_interface_extra}"
    490 	fi
    491 	return 1
    492 }
    493 
    494 # Much of this is gratuitously stolen from /etc/rc.d/network.
    495 enable_network() {
    496 
    497 	# Set up the hostname.
    498 	if [ -f /mnt/etc/myname ]; then
    499 		hostname=$(cat /mnt/etc/myname)
    500 	elif [ -f /mnt/etc/rc.conf ];then
    501 		hostname=$(sh -c '. /mnt/etc/rc.conf ; echo $hostname')
    502 	else
    503 		echo "ERROR: no /etc/myname!"
    504 		return 1
    505 	fi
    506 	if [ -z "$hostname" ];then
    507 		echo "ERROR: hostname not set in /etc/myname or /etc/rc.conf!"
    508 		return 1
    509 	fi
    510 	hostname $hostname
    511 
    512 	# configure all the interfaces which we know about.
    513 if [ -f /mnt/etc/rc.conf ]; then
    514 (
    515 	# assume network interface configuration style 1.2D and up
    516 	if [ -f /mnt/etc/defaults/rc.conf ]; then
    517 		. /mnt/etc/defaults/rc.conf
    518 	fi
    519 	. /mnt/etc/rc.conf
    520 
    521 	if [ "$net_interfaces" != NO ]; then
    522 		if [ "$auto_ifconfig" = YES ]; then
    523 			tmp="$(ifconfig -l)"
    524 		else
    525 			tmp="$net_interfaces"
    526 		fi
    527 		echo -n "configuring network interfaces:"
    528 		for i in $tmp; do
    529 			eval $(echo 'args=$ifconfig_'$i)
    530 			if [ -n "$args" ]; then
    531 				echo -n " $i"
    532 				ifconfig $i $args
    533 			elif [ -f /mnt/etc/ifconfig.$i ]; then
    534 				echo -n " $i"
    535 				(while read args; do
    536 					ifconfig $i $args
    537 				done) < /mnt/etc/ifconfig.$i
    538 			elif [ "$auto_ifconfig" != YES ]; then
    539 				echo
    540 				echo -n "/mnt/etc/ifconfig.$i missing"
    541 				echo -n "& ifconfig_$i not set"
    542 				echo "; interface $i can't be configured"
    543 			fi
    544 		done
    545 		echo "."
    546 	fi
    547 )
    548 else
    549 (
    550 	tmp="$IFS"
    551 	IFS="$IFS."
    552 	set -- $(echo /mnt/etc/hostname*)
    553 	IFS=$tmp
    554 	unset tmp
    555 
    556 	while [ $# -ge 2 ] ; do
    557 		shift		# get rid of "hostname"
    558 		(
    559 			read af name mask bcaddr extras
    560 			read dt dtaddr
    561 
    562 			if [ -z "$name" ]; then
    563 		    echo "/etc/hostname.$1: invalid network configuration file"
    564 				exit
    565 			fi
    566 
    567 			cmd="ifconfig $1 $af $name "
    568 			if [ "${dt}" = "dest" ]; then cmd="$cmd $dtaddr"; fi
    569 			if [ -n "$mask" ]; then cmd="$cmd netmask $mask"; fi
    570 			if [ "${bcaddr:-NONE}" != "NONE" ]; then
    571 				cmd="$cmd broadcast $bcaddr";
    572 			fi
    573 			cmd="$cmd $extras"
    574 
    575 			$cmd
    576 		) < /mnt/etc/hostname.$1
    577 		shift
    578 	done
    579 )
    580 fi
    581 
    582 	# set the address for the loopback interface
    583 	ifconfig lo0 inet localhost
    584 
    585 	# use loopback, not the wire
    586 	route add $hostname localhost
    587 
    588 	# /etc/mygate, if it exists, contains the name of my gateway host
    589 	# that name must be in /etc/hosts.
    590 	if [ -f /mnt/etc/mygate ]; then
    591 		route delete default > /dev/null 2>&1
    592 		route add default $(cat /mnt/etc/mygate)
    593 	fi
    594 
    595 	# enable the resolver, if appropriate.
    596 	if [ -f /mnt/etc/resolv.conf ]; then
    597 		_resolver_enabled="TRUE"
    598 		cp /mnt/etc/resolv.conf /tmp/resolv.conf.shadow
    599 	fi
    600 
    601 	# Display results...
    602 	echo	"Network interface configuration:"
    603 	ifconfig -a
    604 
    605 	echo	""
    606 
    607 	if [ "${_resolver_enabled:-FALSE}" = "TRUE" ]; then
    608 		netstat -r
    609 		echo	""
    610 		echo	"Resolver enabled."
    611 	else
    612 		netstat -rn
    613 		echo	""
    614 		echo	"Resolver not enabled."
    615 	fi
    616 
    617 	return 0
    618 }
    619 
    620 install_ftp() {
    621 	local	_f
    622 	local	_sets
    623 	local	_next
    624 
    625 	# Build a script to extract valid files from a list
    626 	# of filenames on stdin.
    627 	# XXX : Can we use this on more places? Leo.
    628 
    629 	echo "#!/bin/sh" > /tmp/fname_filter.sh
    630 	echo "while read line; do"	>> /tmp/fname_filter.sh
    631 	echo "    case \$line in"	>> /tmp/fname_filter.sh
    632 	for _f in $THESETS; do
    633 		echo "    $_f.tar.gz|$_f.tgz|$_f.tar|$_f.${VERSION}.aa)" \
    634 					>> /tmp/fname_filter.sh
    635 		echo '        echo -n "$line ";;' \
    636 					>> /tmp/fname_filter.sh
    637 	done
    638 	echo "        *) ;;"		>> /tmp/fname_filter.sh
    639 	echo "    esac"			>> /tmp/fname_filter.sh
    640 	echo "done"			>> /tmp/fname_filter.sh
    641 
    642 	# Get several parameters from the user, and create
    643 	# a shell script that directs the appropriate
    644 	# commands into ftp.
    645 	cat << \__install_ftp_1
    646 
    647 This is an automated ftp-based installation process.  You will be asked
    648 several questions.  The correct set of commands will be placed in a script
    649 that will be fed to ftp(1).
    650 
    651 __install_ftp_1
    652 	# Get server IP address
    653 	resp=""		# force one iteration
    654 	while [ -z "${resp}" ]; do
    655 		echo -n "Server IP? [${_ftp_server_ip}] "
    656 		getresp "${_ftp_server_ip}"
    657 		_ftp_server_ip=$resp
    658 	done
    659 
    660 	# Get login name
    661 	resp=""		# force one iteration
    662 	while [ -z "${resp}" ]; do
    663 		echo -n "Login? [${_ftp_server_login}] "
    664 		getresp "${_ftp_server_login}"
    665 		_ftp_server_login=$resp 
    666 	done
    667 
    668 	# Get password
    669 	resp=""		# force one iteration
    670 	while [ -z "${resp}" ]; do
    671 		echo -n "Password? "
    672 		stty -echo
    673 		getresp ""
    674 		echo ""
    675 		stty echo
    676 		_ftp_server_password=$resp
    677 	done
    678 
    679 	cat << \__install_ftp_2
    680 
    681 You will be asked to enter the name of the directory that contains the
    682 installation sets. When you enter a '?' you will see a listing of the
    683 current directory on the server.
    684 __install_ftp_2
    685 	echo ""
    686 	echo "The default installation directory in the official ftp server is:"
    687 	echo "/pub/NetBSD/NetBSD-${RELEASE}/${MACHINE}/binary/sets"
    688 
    689 	_sets=""
    690 	while [ -z "$_sets" ]
    691 	do
    692 		resp=""		# force one iteration
    693 		while [ -z "${resp}" ]; do
    694 			echo -n "Server directory? [${_ftp_server_dir}] "
    695 		    getresp "${_ftp_server_dir}"
    696 		    if [ -z "$resp" ] && [ -z "$_ftp_server_dir" ]; then
    697 			resp=""
    698 		    fi
    699 		done
    700 		if [ $resp != '?' ]; then
    701 			_ftp_server_dir=$resp
    702 		fi
    703 
    704 		# Build the basics of an ftp-script...
    705 		echo "#!/bin/sh" > /tmp/ftp-script.sh
    706 		echo "cd /mnt" >> /tmp/ftp-script.sh
    707 		echo "ftp -e -i -n $_ftp_server_ip << \__end_commands" >> \
    708 		    /tmp/ftp-script.sh
    709 		echo "user $_ftp_server_login $_ftp_server_password" >> \
    710 		    /tmp/ftp-script.sh
    711 		echo "bin" >> /tmp/ftp-script.sh
    712 		echo "cd $_ftp_server_dir" >> /tmp/ftp-script.sh
    713 
    714 		# Make a copy of this script that lists the directory
    715 		# contents, and use that to determine the files to get.
    716 		cat /tmp/ftp-script.sh	>  /tmp/ftp-dir.sh
    717 		echo "nlist"		>> /tmp/ftp-dir.sh
    718 		echo "quit"		>> /tmp/ftp-dir.sh
    719 		echo "__end_commands"	>> /tmp/ftp-dir.sh
    720 
    721 		if [ $resp = '?' ]; then
    722 			sh /tmp/ftp-dir.sh
    723 		else
    724 			_sets=$(sh /tmp/ftp-dir.sh | sort -u | sh /tmp/fname_filter.sh)
    725 		fi
    726 	done
    727 	rm -f /tmp/ftp-dir.sh /tmp/fname_filter.sh
    728 	rm -f /tmp/ftp-script.sh
    729 
    730 	# Prepare ftp-fetch script to fetch binary sets
    731 	_download_dir=INSTALL
    732 	_ftp_opts=""
    733 	_ftp_url="ftp://$_ftp_server_login:$_ftp_server_password@$_ftp_server_ip$_ftp_server_dir/"
    734 	echo "#!/bin/sh" > /tmp/ftp-fetch.sh
    735 	echo "cd /mnt" >> /tmp/ftp-fetch.sh
    736 	echo "mkdir -p $_download_dir" >> /tmp/ftp-fetch.sh
    737 
    738 	while : ; do
    739 		echo "The following sets are available for extraction:"
    740 		echo "(marked sets are already on the extraction list)"
    741 		echo ""
    742 
    743 		_next=""
    744 		for _f in $_sets ; do
    745 			if isin $_f $_setsdone; then
    746 				echo -n "[X] "
    747 				_next=""
    748 			else
    749 				echo -n "    "
    750 				if [ -z "$_next" ]; then _next=$_f; fi
    751 			fi
    752 			echo $_f
    753 		done
    754 		echo ""
    755 
    756 		# Get name of the file and add extraction command
    757 		# to the ftp-fetch script.
    758 		if [ -z "$_next" ]; then resp=n; else resp=y; fi
    759 		echo -n "Continue to add filenames [$resp]? "
    760 		getresp "$resp"
    761 		if [ "$resp" = "n" ]; then
    762 			break
    763 		fi
    764 
    765 		echo -n "File name [$_next]? "
    766 		getresp "$_next"
    767 		if isin $resp $_sets; then
    768 			echo "echo Fetching $resp:" >> \
    769 					/tmp/ftp-fetch.sh
    770 			echo "ftp ${_ftp_opts} -o $_download_dir/$resp ${_ftp_url}$resp" >> \
    771 					/tmp/ftp-fetch.sh
    772 			echo "echo Extracting $resp:" >> \
    773 					/tmp/ftp-fetch.sh
    774 			echo "pax -zr${verbose_flag}pe -f $_download_dir/$resp" >> \
    775 					/tmp/ftp-fetch.sh
    776 			echo "rm -f $_download_dir/$resp" >> \
    777 					/tmp/ftp-fetch.sh
    778 			_setsdone="$resp $_setsdone"
    779 		else
    780 			echo "You entered an invalid filename."
    781 			echo ""
    782 		fi
    783 	done
    784 
    785 	sh /tmp/ftp-fetch.sh
    786 	rm -f /tmp/ftp-fetch.sh
    787 	echo "Extraction complete."
    788 }
    789 
    790 install_from_mounted_fs() {
    791 	# $1 - directory containing installation sets
    792 	local _filename
    793 	local _sets
    794 	local _next
    795 	local _all
    796 	local _f
    797 	local _dirname
    798 
    799 	_dirname=$1
    800 	_sets=""
    801 
    802 	if ! dir_has_sets ${_dirname} $THESETS
    803 	then
    804 
    805 		echo ""
    806 		echo "The directory at the mount point, \"${_dirname}\", contains: "
    807 		echo ""
    808 		ls -F ${_dirname}
    809 		echo ""
    810 		echo    "Enter the subdirectory relative to the mountpoint, that"
    811 		echo -n "contains the savesets: [try this directory] "
    812 		getresp ""
    813 		if [ -n "${resp}" ]; then
    814 			_dirname=${_dirname}/$resp
    815 		fi
    816 
    817 		while ! dir_has_sets ${_dirname} $THESETS; do
    818 			echo ""
    819 			echo -n "There are no NetBSD install sets available in "
    820 			echo "\"${_dirname}\"."
    821 			echo "\"${_dirname}\" contains: "
    822 			echo ""
    823 			ls -F ${_dirname}
    824 			echo ""
    825 			echo -n "Enter subdirectory: [try other install media] "
    826 			getresp ""
    827 			if [ -z "${resp}" ]; then
    828 				return
    829 			fi
    830 			if [ ! -d ${_dirname}/${resp} ]; then
    831 				echo "\"${resp}\" is no directory; try again."
    832 			else
    833 				_dirname=${_dirname}/$resp
    834 			fi
    835 		done
    836 	fi
    837 
    838 	for _f in $THESETS ; do
    839 		if [ -f ${_dirname}/${_f}.tar.gz ]; then
    840 			_sets="$_sets ${_f}.tar.gz"
    841 		elif [ -f ${_dirname}/${_f}.tgz ]; then
    842 			_sets="$_sets ${_f}.tgz"
    843 		elif [ -f ${_dirname}/${_f}.tar ]; then
    844 			_sets="$_sets ${_f}.tar"
    845 		elif [ -f ${_dirname}/${_f}${VERSION}.aa ]; then
    846 			_sets="$_sets ${_f}${VERSION}"
    847 		fi
    848 	done
    849 
    850 	while : ; do
    851 		echo "The following sets are available for extraction:"
    852 		echo "(marked sets have already been extracted)"
    853 		echo ""
    854 
    855 		_next=""
    856 		_all=""
    857 		for _f in $_sets ; do
    858 			if isin $_f $_setsdone; then
    859 				echo -n "[X] "
    860 				_next=""
    861 			else
    862 				echo -n "    "
    863 				if [ -z "$_next" ]; then
    864 					_next=$_f;
    865 				fi
    866 				_all="$_all $_f"
    867 			fi
    868 			echo $_f
    869 		done
    870 		echo ""
    871 
    872 		# Get the name of the file.
    873 		if [ -z "$_next" ]; then
    874 			resp=n
    875 		else
    876 			resp=y
    877 		fi
    878 		echo -n "Continue extraction [$resp]?"
    879 		getresp "$resp"
    880 		if [ "$resp" = "n" ]; then
    881 			break
    882 		fi
    883 
    884 		echo -n "File name(s) (or "all") [$_next]? "
    885 		getresp "$_next"
    886 		if [ "x$resp" = xall ]; then
    887 			resp="$_all"
    888 		fi
    889 
    890 		for _f in $resp; do
    891 			_filename="/${_dirname}/$_f"
    892 
    893 			# Ensure file exists
    894 			if [ ! -f $_filename ]; then
    895 				if [ -f ${_filename}.aa ]; then
    896 					_filename=${_filename}.\?\?
    897 				else
    898 			 echo "File $_filename does not exist.  Check to make"
    899 			 echo "sure you entered the information properly."
    900 			 continue 2
    901 				fi
    902 			fi
    903 
    904 			# Extract file
    905 			echo "Extracting the $_f set:"
    906 			case "$_filename" in
    907 			*.tar)
    908 				(cd /mnt; pax -r${verbose_flag}pe < $_filename)
    909 				;;
    910 			*)
    911 				cat $_filename | \
    912 					(cd /mnt; pax -zr${verbose_flag}pe)
    913 				;;
    914 			esac
    915 			echo "Extraction complete."
    916 			_setsdone="$_f $_setsdone"
    917 		done
    918 
    919 	done
    920 }
    921 
    922 install_cdrom() {
    923 	local _drive
    924 	local _partition_range
    925 	local _partition
    926 	local _fstype
    927 	local _directory
    928 
    929 	# Get the cdrom device info
    930 	cat << \__install_cdrom_1
    931 
    932 The following CD-ROM devices are installed on your system; please select
    933 the CD-ROM device containing the partition with the installation sets:
    934 
    935 __install_cdrom_1
    936 	_CDDEVS=$(md_get_cddevs)
    937 	echo    "$_CDDEVS"
    938 	echo	""
    939 	echo -n	"Which is the CD-ROM with the installation media? [abort] "
    940 	getresp "abort"
    941 	case "$resp" in
    942 		abort)
    943 			echo "Aborting."
    944 			return
    945 			;;
    946 
    947 		*)
    948 			if isin $resp $_CDDEVS ; then
    949 				_drive=$resp
    950 			else
    951 				echo ""
    952 				echo "The CD-ROM $resp does not exist."
    953 				echo "Aborting."
    954 				return
    955 			fi
    956 			;;
    957 	esac
    958 
    959 	# Get partition
    960 	_partition_range=$(md_get_partition_range)
    961 	resp=""		# force one iteration
    962 	while [ -z "${resp}" ]; do
    963 		echo -n "Partition? [a] "
    964 		getresp "a"
    965 		case "$resp" in
    966 			$_partition_range)
    967 				_partition=$resp
    968 				;;
    969 
    970 			*)
    971 				echo "Invalid response: $resp"
    972 				resp=""		# force loop to repeat
    973 				;;
    974 		esac
    975 	done
    976 
    977 	# Ask for filesystem type
    978 	cat << \__install_cdrom_2
    979 
    980 There are two CD-ROM filesystem types currently supported by this program:
    981 	1) ISO-9660 (cd9660)
    982 	2) Berkeley Fast Filesystem (ffs)
    983 
    984 __install_cdrom_2
    985 	resp=""		# force one iteration
    986 	while [ -z "${resp}" ]; do
    987 		echo -n "Which filesystem type? [cd9660] "
    988 		getresp "cd9660"
    989 		case "$resp" in
    990 			cd9660|ffs)
    991 				_fstype=$resp
    992 				;;
    993 
    994 			*)
    995 				echo "Invalid response: $resp"
    996 				resp=""		# force loop to repeat
    997 				;;
    998 		esac
    999 	done
   1000 
   1001 	# Mount the CD-ROM
   1002 	if ! mount -t ${_fstype} -o ro \
   1003 	    /dev/${_drive}${_partition} /mnt2 ; then
   1004 		echo "Cannot mount CD-ROM drive.  Aborting."
   1005 		return
   1006 	fi
   1007 
   1008 	install_from_mounted_fs /mnt2
   1009 	umount -f /mnt2 > /dev/null 2>&1
   1010 }
   1011 
   1012 mount_a_disk() {
   1013 	# Mount a disk on /mnt2. The set of disk devices to choose from
   1014 	# is $_DKDEVS.
   1015 	# returns 0 on failure.
   1016 
   1017 	local _drive
   1018 	local _partition_range
   1019 	local _partition
   1020 	local _fstype
   1021 	local _fsopts
   1022 	local _directory
   1023 	local _md_fstype
   1024 	local _md_fsopts
   1025 
   1026 	getresp "abort"
   1027 	case "$resp" in
   1028 		abort)
   1029 			echo "Aborting."
   1030 			return 0
   1031 			;;
   1032 
   1033 		*)
   1034 			if isin $resp $_DKDEVS ; then
   1035 				_drive=$resp
   1036 			else
   1037 				echo ""
   1038 				echo "The disk $resp does not exist."
   1039 				echo "Aborting."
   1040 				return 0
   1041 			fi
   1042 			;;
   1043 	esac
   1044 
   1045 	# Get partition
   1046 	_partition_range=$(md_get_partition_range)
   1047 	resp=""		# force one iteration
   1048 	while [ -z "${resp}" ]; do
   1049 		echo -n "Partition? [d] "
   1050 		getresp "d"
   1051 		case "$resp" in
   1052 			$_partition_range)
   1053 				_partition=$resp
   1054 				;;
   1055 
   1056 			*)
   1057 				echo "Invalid response: $resp"
   1058 				resp=""		# force loop to repeat
   1059 				;;
   1060 		esac
   1061 	done
   1062 
   1063 	# Ask for filesystem type
   1064 	cat << \__mount_a_disk_2
   1065 
   1066 The following filesystem types are supported:
   1067 	1) ffs
   1068 	2) cd9660
   1069 __mount_a_disk_2
   1070 	_md_fstype=$(md_native_fstype)
   1071 	_md_fsopts=$(md_native_fsopts)
   1072 	if [ -n "$_md_fstype" ]; then
   1073 		echo "	3) $_md_fstype"
   1074 	else
   1075 		_md_fstype="_undefined_"
   1076 	fi
   1077 	resp=""		# force one iteration
   1078 	while [ -z "${resp}" ]; do
   1079 		echo -n "Which filesystem type? [ffs] "
   1080 		getresp "ffs"
   1081 		case "$resp" in
   1082 			ffs|cd9660)
   1083 				_fstype=$resp
   1084 				_fsopts="ro"
   1085 				;;
   1086 			$_md_fstype)
   1087 				_fstype=$resp
   1088 				_fsopts=$_md_fsopts
   1089 				;;
   1090 			*)
   1091 				echo "Invalid response: $resp"
   1092 				resp=""		# force loop to repeat
   1093 				;;
   1094 		esac
   1095 	done
   1096 
   1097 	# Mount the disk
   1098 	if ! mount -t ${_fstype} -o $_fsopts \
   1099 	    /dev/${_drive}${_partition} /mnt2 ; then
   1100 		echo "Cannot mount disk.  Aborting."
   1101 		return 0
   1102 	fi
   1103 	return 1
   1104 }
   1105 
   1106 install_disk() {
   1107 	local _directory
   1108 
   1109 	cat << \__install_disk_1
   1110 
   1111 Ok, lets install from a disk.  The file-system the install sets on may
   1112 already mounted, or we might have to mount the filesystem to get to it.
   1113 
   1114 __install_disk_1
   1115 
   1116 	echo -n "Is the file-system with the install sets already mounted? [n] "
   1117 	getresp "n"
   1118 	case $resp in
   1119 	y*|Y*)
   1120 		echo "What mount point are the sets located in? [] "
   1121 		getresp ""
   1122 		if [ -d "$resp" ]; then
   1123 			install_from_mounted_fs $resp
   1124 		else
   1125 			echo "$resp: Not a directory, aborting..."
   1126 		fi
   1127 		return
   1128 		;;
   1129 	*)
   1130 		;;
   1131 	esac
   1132 
   1133 	cat << \__install_disk_2
   1134 
   1135 The following disk devices are installed on your system; please select
   1136 the disk device containing the partition with the installation sets:
   1137 
   1138 __install_disk_2
   1139 	_DKDEVS=$(md_get_diskdevs)
   1140 	echo    "$_DKDEVS"
   1141 	echo	""
   1142 	echo -n	"Which is the disk with the installation sets? [abort] "
   1143 
   1144 	if mount_a_disk ; then
   1145 		return
   1146 	fi
   1147 
   1148 	install_from_mounted_fs /mnt2
   1149 	umount -f /mnt2 > /dev/null 2>&1
   1150 }
   1151 
   1152 install_nfs() {
   1153 	# Get the IP address of the server
   1154 	resp=""		# force one iteration
   1155 	while [ -z "${resp}" ]; do
   1156 		echo -n "Server IP address? [${_nfs_server_ip}] "
   1157 		getresp "${_nfs_server_ip}"
   1158 	done
   1159 	_nfs_server_ip=$resp
   1160 
   1161 	# Get server path to mount
   1162 	resp=""		# force one iteration
   1163 	while [ -z "${resp}" ]; do
   1164 		echo -n "Filesystem on server to mount? [${_nfs_server_path}] "
   1165 		getresp "${_nfs_server_path}"
   1166 	done
   1167 	_nfs_server_path=$resp
   1168 
   1169 	# Determine use of TCP
   1170 	echo -n "Use TCP transport (only works with capable NFS server)? [n] "
   1171 	getresp "n"
   1172 	case "$resp" in
   1173 		y*|Y*)
   1174 			_nfs_tcp="-T"
   1175 			;;
   1176 
   1177 		*)
   1178 			echo -n "Use small NFS transfers (needed when server "
   1179 			echo "or client"
   1180 			echo -n "has a slow network card)? [n] "
   1181 			getresp "n"
   1182 			case "$resp" in
   1183 			y*|Y*)
   1184 				_nfs_tcp="-r 1024 -w 1024"
   1185 				;;
   1186 
   1187 			*)
   1188 				_nfs_tcp=""
   1189 				;;
   1190 			esac
   1191 			;;
   1192 	esac
   1193 
   1194 	# Mount the server
   1195 	mkdir /mnt2 > /dev/null 2>&1
   1196 	if ! mount_nfs $_nfs_tcp ${_nfs_server_ip}:${_nfs_server_path} \
   1197 	    /mnt2 ; then
   1198 		echo "Cannot mount NFS server.  Aborting."
   1199 		return
   1200 	fi
   1201 
   1202 	install_from_mounted_fs /mnt2
   1203 	umount -f /mnt2 > /dev/null 2>&1
   1204 }
   1205 
   1206 install_tape() {
   1207 	local _xcmd
   1208 
   1209 	# Get the name of the tape from the user.
   1210 	cat << \__install_tape_1
   1211 
   1212 The installation program needs to know which tape device to use.  Make
   1213 sure you use a "no rewind on close" device.
   1214 
   1215 __install_tape_1
   1216 	_tape=$(basename $TAPE)
   1217 	resp=""		# force one iteration
   1218 	while [ -z "${resp}" ]; do
   1219 		echo -n "Name of tape device? [${_tape}]"
   1220 		getresp "${_tape}"
   1221 	done
   1222 	_tape=$(basename $resp)
   1223 	TAPE="/dev/${_tape}"
   1224 	if [ ! -c $TAPE ]; then
   1225 		echo "$TAPE does not exist or is not a character special file."
   1226 		echo "Aborting."
   1227 		return
   1228 	fi
   1229 	export TAPE
   1230 
   1231 	# Rewind the tape device
   1232 	echo -n "Rewinding tape..."
   1233 	if ! mt rewind ; then
   1234 		echo "$TAPE may not be attached to the system or may not be"
   1235 		echo "a tape device.  Aborting."
   1236 		return
   1237 	fi
   1238 	echo "done."
   1239 
   1240 	# Get the file number
   1241 	resp=""		# force one iteration
   1242 	while [ -z "${resp}" ]; do
   1243 		echo -n "File number? "
   1244 		getresp ""
   1245 		case "$resp" in
   1246 			[1-9]*)
   1247 				_nskip=$(expr $resp - 1)
   1248 				;;
   1249 
   1250 			*)
   1251 				echo "Invalid file number ${resp}."
   1252 				resp=""		# fore loop to repeat
   1253 				;;
   1254 		esac
   1255 	done
   1256 
   1257 	# Skip to correct file.
   1258 	echo -n "Skipping to source file..."
   1259 	if [ "${_nskip}" != "0" ]; then
   1260 		if ! mt fsf $_nskip ; then
   1261 			echo "Could not skip $_nskip files.  Aborting."
   1262 			return
   1263 		fi
   1264 	fi
   1265 	echo "done."
   1266 
   1267 	cat << \__install_tape_2
   1268 
   1269 There are 2 different ways the file can be stored on tape:
   1270 
   1271 	1) an image of a gzipped tar file
   1272 	2) a standard tar image
   1273 
   1274 __install_tape_2
   1275 	resp=""		# force one iteration
   1276 	while [ -z "${resp}" ]; do
   1277 		echo -n "Which way is it? [1] "
   1278 		getresp "1"
   1279 		case "$resp" in
   1280 		1)
   1281 			_xcmd="pax -zr${verbose_flag}pe"
   1282 			;;
   1283 
   1284 		2)
   1285 			_xcmd="pax -r${verbose_flag}pe"
   1286 			;;
   1287 
   1288 		*)
   1289 			echo "Invalid response: $resp."
   1290 			resp=""		# force loop to repeat
   1291 			;;
   1292 		esac
   1293 		( cd /mnt; dd if=$TAPE | $_xcmd )
   1294 	done
   1295 	echo "Extraction complete."
   1296 }
   1297 
   1298 get_timezone() {
   1299 	local _a
   1300 	local _zonepath
   1301 
   1302 	#
   1303 	# If the zoneinfo is not on the installation medium or on the
   1304 	# installed filesystem, set TZ to GMT and return immediatly.
   1305 	#
   1306 	if [ ! -e /usr/share/zoneinfo ] && [ ! -e /mnt/usr/share/zoneinfo ]; then
   1307 		TZ=GMT
   1308 		return
   1309 	fi
   1310 	if [ ! -d /usr/share/zoneinfo ]; then
   1311 		_zonepath=/mnt
   1312 	else
   1313 		_zonepath=""
   1314 	fi
   1315 		
   1316 cat << \__get_timezone_1
   1317 
   1318 Select a time zone for your location. Timezones are represented on the
   1319 system by a directory structure rooted in "/usr/share/zoneinfo". Most
   1320 timezones can be selected by entering a token like "MET" or "GMT-6".
   1321 Other zones are grouped by continent, with detailed zone information
   1322 separated by a slash ("/"), e.g. "US/Pacific".
   1323 
   1324 To get a listing of what's available in /usr/share/zoneinfo, enter "?"
   1325 at the prompts below.
   1326 
   1327 __get_timezone_1
   1328 	if [ -z "$TZ" ]; then
   1329 		TZ=$(ls -l /mnt/etc/localtime 2>/dev/null | cutlast)
   1330 		TZ=${TZ#/usr/share/zoneinfo/}
   1331 	fi
   1332 	while :; do
   1333 		echo -n	"What timezone are you in ['?' for list] [$TZ]? "
   1334 		getresp "$TZ"
   1335 		case "$resp" in
   1336 		"")
   1337 			echo "Timezone defaults to GMT"
   1338 			TZ="GMT"
   1339 			break;
   1340 			;;
   1341 		"?")
   1342 			ls ${_zonepath}/usr/share/zoneinfo
   1343 			;;
   1344 		*)
   1345 			_a=$resp
   1346 			while [ -d ${_zonepath}/usr/share/zoneinfo/$_a ]; do
   1347 				echo -n "There are several timezones available"
   1348 				echo " within zone '$_a'"
   1349 				echo -n "Select a sub-timezone ['?' for list]: "
   1350 				getresp ""
   1351 				case "$resp" in
   1352 				"?") ls ${_zonepath}/usr/share/zoneinfo/$_a ;;
   1353 				*)	_a=${_a}/${resp}
   1354 					if [ -f ${_zonepath}/usr/share/zoneinfo/$_a ]; then
   1355 						break;
   1356 					fi
   1357 					;;
   1358 				esac
   1359 			done
   1360 			if [ -f ${_zonepath}/usr/share/zoneinfo/$_a ]; then
   1361 				TZ="$_a"
   1362 				echo "You have selected timezone \"$_a\"".
   1363 				break 2
   1364 			fi
   1365 			echo "'/usr/share/zoneinfo/$_a' is not a valid timezone on this system."
   1366 			;;
   1367 		esac
   1368 	done
   1369 }
   1370 
   1371 install_sets()
   1372 {
   1373 	local _yup
   1374 	_yup="FALSE"
   1375 
   1376 	# Ask the user which media to load the distribution from.
   1377 	# Ask the user if they want verbose extraction.  They might not want
   1378 	# it on, eg, SPARC frame buffer console.
   1379 	cat << \__install_sets_1
   1380 
   1381 It is now time to extract the installation sets onto the hard disk.
   1382 Make sure the sets are either on a local device (i.e. tape, CD-ROM) or on a
   1383 network server.
   1384 
   1385 Would you like to see each file listed during extraction (verbose) mode?
   1386 On some console hardware, such as serial consoles and Sun frame buffers,
   1387 this can extend the total extraction time.
   1388 __install_sets_1
   1389 	echo -n "Use verbose listing for extractions? [y] "
   1390 	getresp "y"
   1391 	case "$resp" in
   1392 	y*|Y*)
   1393 		verbose_flag=v
   1394 		;;
   1395 	*)
   1396 		echo "Not using verbose listing."
   1397 		verbose_flag=""
   1398 		;;
   1399 	esac
   1400 
   1401 	if [ -d ${Default_sets_dir:-/dev/null} ]; then
   1402 		if dir_has_sets $Default_sets_dir $THESETS; then
   1403 			local_sets_dir=$Default_sets_dir
   1404 		fi
   1405 	fi
   1406 	if [ -n "${local_sets_dir}" ]; then
   1407 		install_from_mounted_fs ${local_sets_dir}
   1408 		if [ -n "$_setsdone" ]; then
   1409 			_yup="TRUE"
   1410 		fi
   1411 	fi
   1412 
   1413 	# Go on prodding for alternate locations
   1414 	resp=""		# force at least one iteration
   1415 	while [ -z "${resp}" ]; do
   1416 		# If _yup is not FALSE, it means that we extracted sets above.
   1417 		# If that's the case, bypass the menu the first time.
   1418 		if [ "${_yup}" = "FALSE" ]; then
   1419 			echo -n	"Install from (f)tp, (t)ape, (C)D-ROM, (N)FS"
   1420 			echo -n " or local (d)isk? "
   1421 			getresp ""
   1422 			case "$resp" in
   1423 			d*|D*)
   1424 				install_disk
   1425 				;;
   1426 			f*|F*)
   1427 				install_ftp
   1428 				;;
   1429 			t*|T*)
   1430 				install_tape
   1431 				;;
   1432 			c*|C*)
   1433 				install_cdrom
   1434 				;;
   1435 			n*|N*)
   1436 				install_nfs
   1437 				;;
   1438 			*)
   1439 				echo "Invalid response: $resp"
   1440 				resp=""
   1441 				;;
   1442 			esac
   1443 		else
   1444 			_yup="FALSE"	# So we'll ask next time
   1445 		fi
   1446 
   1447 		# Give the user the opportunity to extract more sets. They
   1448 		# don't necessarily have to come from the same media.
   1449 		echo	""
   1450 		echo -n	"Extract more sets? [n] "
   1451 		getresp "n"
   1452 		case "$resp" in
   1453 		y*|Y*)
   1454 			# Force loop to repeat
   1455 			resp=""
   1456 			;;
   1457 
   1458 		*)
   1459 			;;
   1460 		esac
   1461 	done
   1462 }
   1463 
   1464 munge_fstab()
   1465 {
   1466 	local _fstab
   1467 	local _fstab_shadow
   1468 	local _dev
   1469 	local _mp
   1470 	local _fstype
   1471 	local _rest
   1472 
   1473 	# Now that the 'real' fstab is configured, we munge it into a 'shadow'
   1474 	# fstab which we'll use for mounting and unmounting all of the target
   1475 	# filesystems relative to /mnt.  Mount all filesystems.
   1476 	_fstab=$1
   1477 	_fstab_shadow=$2
   1478 	( while read _dev _mp _fstype _rest; do
   1479 		# Skip comment lines
   1480 		case "$_dev" in
   1481 			\#*)	continue;;
   1482 			*)	;;
   1483 		esac
   1484 		# and some filesystem types (like there are swap,kernfs,...)
   1485 		case "$_fstype" in
   1486 			ffs|ufs|nfs)	;;
   1487 			*)	continue;;
   1488 		esac
   1489 		if [ "$_mp" = "/" ]; then
   1490 			echo $_dev /mnt $_fstype $_rest
   1491 		else
   1492 			echo $_dev /mnt$_mp $_fstype $_rest
   1493 		fi
   1494 	    done ) < $_fstab > $_fstab_shadow
   1495 }
   1496 
   1497 mount_fs()
   1498 {
   1499 	# Must mount filesystems manually, one at a time, so we can make
   1500 	# sure the mount points exist.
   1501 	# $1 is a file in fstab format
   1502 	local _fstab
   1503 
   1504 	_fstab=$1
   1505 
   1506 	( while read line; do
   1507 		set -- $line
   1508 		_dev=$1
   1509 		_mp=$2
   1510 		_fstype=$3
   1511 		_opt=$4
   1512 
   1513 		# If not the root filesystem, make sure the mount
   1514 		# point is present.
   1515 		if [ "$_mp" != "/mnt" ]; then
   1516 			mkdir -p $_mp
   1517 		fi
   1518 
   1519 		# Mount the filesystem.  If the mount fails, exit
   1520 		# with an error condition to tell the outer
   1521 		# later to bail.
   1522 		if ! mount -v -t $_fstype -o async -o $_opt $_dev $_mp ; then
   1523 			# error message displated by mount
   1524 			exit 1
   1525 		fi
   1526 	done ) < $_fstab
   1527 
   1528 	if [ "$?" != "0" ]; then
   1529 		cat << \__mount_filesystems_1
   1530 
   1531 FATAL ERROR:  Cannot mount filesystems.  Double-check your configuration
   1532 and restart the installation process.
   1533 __mount_filesystems_1
   1534 		exit
   1535 	fi
   1536 }
   1537 
   1538 unmount_fs()
   1539 {
   1540 	# Unmount all filesystems and check their integrity.
   1541 	# Usage: [-fast] <fstab file>
   1542 	local _fast
   1543 	local _fstab
   1544 	local _pid
   1545 
   1546 	if [ "$1" = "-fast" ]; then
   1547 		_fast=1
   1548 		_fstab=$2
   1549 	else
   1550 		_fast=0
   1551 		_fstab=$1
   1552 	fi
   1553 
   1554 	if ! [ -f "${_fstab}" ] || ! [ -s "${_fstab}" ]; then
   1555 		echo "fstab empty" > /dev/tty
   1556 		return
   1557 	fi
   1558 
   1559 	if [ $_fast = 0 ]; then
   1560 		echo -n	"Syncing disks..."
   1561 		_pid=$(twiddle)
   1562 		sync; sleep 4; sync; sleep 2; sync; sleep 2
   1563 		kill $_pid
   1564 		echo	"done."
   1565 	fi
   1566 
   1567 	(
   1568 		_devs=""
   1569 		_mps=""
   1570 		# maintain reverse order
   1571 		while read line; do
   1572 			set -- $line
   1573 			_devs="$1 ${_devs}"
   1574 			_mps="$2 ${_mps}"
   1575 		done
   1576 		echo -n "Umounting filesystems... "
   1577 		for _mp in ${_mps}; do
   1578 			echo -n "${_mp} "
   1579 			umount ${_mp}
   1580 		done
   1581 		echo "Done."
   1582 
   1583 		if [ $_fast = 0 ]; then
   1584 			exit
   1585 		fi
   1586 		echo "Checking filesystem integrity..."
   1587 		for _dev in ${_devs}; do
   1588 			echo  "${_dev}"
   1589 			fsck -f ${_dev}
   1590 		done
   1591 		echo "Done."
   1592 	) < $_fstab
   1593 }
   1594 
   1595 check_fs()
   1596 {
   1597 	# Check filesystem integrity.
   1598 	# $1 is a file in fstab format
   1599 	local _fstab
   1600 
   1601 	_fstab=$1
   1602 
   1603 	(
   1604 		_devs=""
   1605 		_mps=""
   1606 		while read line; do
   1607 			set -- $line
   1608 			_devs="$1 ${_devs}"
   1609 			_mps="$2 ${_mps}"
   1610 		done
   1611 
   1612 		echo "Checking filesystem integrity..."
   1613 		for _dev in ${_devs}; do
   1614 			echo  "${_dev}"
   1615 			fsck -f ${_dev}
   1616 		done
   1617 		echo "Done."
   1618 	) < $_fstab
   1619 }
   1620 
   1621 mi_mount_kernfs() {
   1622 	# Make sure kernfs is mounted.
   1623 	if [ ! -d /kern ] || [ ! -e /kern/msgbuf ]; then
   1624 		mkdir /kern > /dev/null 2>&1
   1625 		/sbin/mount_kernfs /kern /kern
   1626 	fi
   1627 }
   1628 
   1629 mi_filter_msgbuf() {
   1630 	# Remove timestemps, sort.
   1631 	sed -e 's/^\[[0-9. ]*\] //' < /kern/msgbuf | sort -u
   1632 }
   1633 
   1634 mi_filter_dmesg() {
   1635 	# Remove timestemps, sort.
   1636 	dmesg | awk '{ h=$0; gsub("^[[0-9. ]*] ", "", h); print h; }' \
   1637 	    | sort -u
   1638 }
   1639