Home | History | Annotate | Line # | Download | only in miniroot
install.sub revision 1.58
      1 #!/bin/sh
      2 #	$NetBSD: install.sub,v 1.58 2020/12/05 18:57: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 
    729 	while : ; do
    730 		echo "The following sets are available for extraction:"
    731 		echo "(marked sets are already on the extraction list)"
    732 		echo ""
    733 
    734 		_next=""
    735 		for _f in $_sets ; do
    736 			if isin $_f $_setsdone; then
    737 				echo -n "[X] "
    738 				_next=""
    739 			else
    740 				echo -n "    "
    741 				if [ -z "$_next" ]; then _next=$_f; fi
    742 			fi
    743 			echo $_f
    744 		done
    745 		echo ""
    746 
    747 		# Get name of the file and add extraction command
    748 		# to the ftp-script.
    749 		if [ -z "$_next" ]; then resp=n; else resp=y; fi
    750 		echo -n "Continue to add filenames [$resp]? "
    751 		getresp "$resp"
    752 		if [ "$resp" = "n" ]; then
    753 			break
    754 		fi
    755 
    756 		echo -n "File name [$_next]? "
    757 		getresp "$_next"
    758 		if isin $resp $_sets; then
    759 			echo "get $resp |\"pax -zr${verbose_flag}pe\"" >> \
    760 					/tmp/ftp-script.sh
    761 			_setsdone="$resp $_setsdone"
    762 		else
    763 			echo "You entered an invalid filename."
    764 			echo ""
    765 		fi
    766 	done
    767 
    768 	echo "quit" >> /tmp/ftp-script.sh
    769 	echo "__end_commands" >> /tmp/ftp-script.sh
    770 
    771 	sh /tmp/ftp-script.sh
    772 	rm -f /tmp/ftp-script.sh
    773 	echo "Extraction complete."
    774 }
    775 
    776 install_from_mounted_fs() {
    777 	# $1 - directory containing installation sets
    778 	local _filename
    779 	local _sets
    780 	local _next
    781 	local _all
    782 	local _f
    783 	local _dirname
    784 
    785 	_dirname=$1
    786 	_sets=""
    787 
    788 	if ! dir_has_sets ${_dirname} $THESETS
    789 	then
    790 
    791 		echo ""
    792 		echo "The directory at the mount point, \"${_dirname}\", contains: "
    793 		echo ""
    794 		ls -F ${_dirname}
    795 		echo ""
    796 		echo    "Enter the subdirectory relative to the mountpoint, that"
    797 		echo -n "contains the savesets: [try this directory] "
    798 		getresp ""
    799 		if [ -n "${resp}" ]; then
    800 			_dirname=${_dirname}/$resp
    801 		fi
    802 
    803 		while ! dir_has_sets ${_dirname} $THESETS; do
    804 			echo ""
    805 			echo -n "There are no NetBSD install sets available in "
    806 			echo "\"${_dirname}\"."
    807 			echo "\"${_dirname}\" contains: "
    808 			echo ""
    809 			ls -F ${_dirname}
    810 			echo ""
    811 			echo -n "Enter subdirectory: [try other install media] "
    812 			getresp ""
    813 			if [ -z "${resp}" ]; then
    814 				return
    815 			fi
    816 			if [ ! -d ${_dirname}/${resp} ]; then
    817 				echo "\"${resp}\" is no directory; try again."
    818 			else
    819 				_dirname=${_dirname}/$resp
    820 			fi
    821 		done
    822 	fi
    823 
    824 	for _f in $THESETS ; do
    825 		if [ -f ${_dirname}/${_f}.tar.gz ]; then
    826 			_sets="$_sets ${_f}.tar.gz"
    827 		elif [ -f ${_dirname}/${_f}.tgz ]; then
    828 			_sets="$_sets ${_f}.tgz"
    829 		elif [ -f ${_dirname}/${_f}.tar ]; then
    830 			_sets="$_sets ${_f}.tar"
    831 		elif [ -f ${_dirname}/${_f}${VERSION}.aa ]; then
    832 			_sets="$_sets ${_f}${VERSION}"
    833 		fi
    834 	done
    835 
    836 	while : ; do
    837 		echo "The following sets are available for extraction:"
    838 		echo "(marked sets have already been extracted)"
    839 		echo ""
    840 
    841 		_next=""
    842 		_all=""
    843 		for _f in $_sets ; do
    844 			if isin $_f $_setsdone; then
    845 				echo -n "[X] "
    846 				_next=""
    847 			else
    848 				echo -n "    "
    849 				if [ -z "$_next" ]; then
    850 					_next=$_f;
    851 				fi
    852 				_all="$_all $_f"
    853 			fi
    854 			echo $_f
    855 		done
    856 		echo ""
    857 
    858 		# Get the name of the file.
    859 		if [ -z "$_next" ]; then
    860 			resp=n
    861 		else
    862 			resp=y
    863 		fi
    864 		echo -n "Continue extraction [$resp]?"
    865 		getresp "$resp"
    866 		if [ "$resp" = "n" ]; then
    867 			break
    868 		fi
    869 
    870 		echo -n "File name(s) (or "all") [$_next]? "
    871 		getresp "$_next"
    872 		if [ "x$resp" = xall ]; then
    873 			resp="$_all"
    874 		fi
    875 
    876 		for _f in $resp; do
    877 			_filename="/${_dirname}/$_f"
    878 
    879 			# Ensure file exists
    880 			if [ ! -f $_filename ]; then
    881 				if [ -f ${_filename}.aa ]; then
    882 					_filename=${_filename}.\?\?
    883 				else
    884 			 echo "File $_filename does not exist.  Check to make"
    885 			 echo "sure you entered the information properly."
    886 			 continue 2
    887 				fi
    888 			fi
    889 
    890 			# Extract file
    891 			echo "Extracting the $_f set:"
    892 			case "$_filename" in
    893 			*.tar)
    894 				(cd /mnt; pax -r${verbose_flag}pe < $_filename)
    895 				;;
    896 			*)
    897 				cat $_filename | \
    898 					(cd /mnt; pax -zr${verbose_flag}pe)
    899 				;;
    900 			esac
    901 			echo "Extraction complete."
    902 			_setsdone="$_f $_setsdone"
    903 		done
    904 
    905 	done
    906 }
    907 
    908 install_cdrom() {
    909 	local _drive
    910 	local _partition_range
    911 	local _partition
    912 	local _fstype
    913 	local _directory
    914 
    915 	# Get the cdrom device info
    916 	cat << \__install_cdrom_1
    917 
    918 The following CD-ROM devices are installed on your system; please select
    919 the CD-ROM device containing the partition with the installation sets:
    920 
    921 __install_cdrom_1
    922 	_CDDEVS=$(md_get_cddevs)
    923 	echo    "$_CDDEVS"
    924 	echo	""
    925 	echo -n	"Which is the CD-ROM with the installation media? [abort] "
    926 	getresp "abort"
    927 	case "$resp" in
    928 		abort)
    929 			echo "Aborting."
    930 			return
    931 			;;
    932 
    933 		*)
    934 			if isin $resp $_CDDEVS ; then
    935 				_drive=$resp
    936 			else
    937 				echo ""
    938 				echo "The CD-ROM $resp does not exist."
    939 				echo "Aborting."
    940 				return
    941 			fi
    942 			;;
    943 	esac
    944 
    945 	# Get partition
    946 	_partition_range=$(md_get_partition_range)
    947 	resp=""		# force one iteration
    948 	while [ -z "${resp}" ]; do
    949 		echo -n "Partition? [a] "
    950 		getresp "a"
    951 		case "$resp" in
    952 			$_partition_range)
    953 				_partition=$resp
    954 				;;
    955 
    956 			*)
    957 				echo "Invalid response: $resp"
    958 				resp=""		# force loop to repeat
    959 				;;
    960 		esac
    961 	done
    962 
    963 	# Ask for filesystem type
    964 	cat << \__install_cdrom_2
    965 
    966 There are two CD-ROM filesystem types currently supported by this program:
    967 	1) ISO-9660 (cd9660)
    968 	2) Berkeley Fast Filesystem (ffs)
    969 
    970 __install_cdrom_2
    971 	resp=""		# force one iteration
    972 	while [ -z "${resp}" ]; do
    973 		echo -n "Which filesystem type? [cd9660] "
    974 		getresp "cd9660"
    975 		case "$resp" in
    976 			cd9660|ffs)
    977 				_fstype=$resp
    978 				;;
    979 
    980 			*)
    981 				echo "Invalid response: $resp"
    982 				resp=""		# force loop to repeat
    983 				;;
    984 		esac
    985 	done
    986 
    987 	# Mount the CD-ROM
    988 	if ! mount -t ${_fstype} -o ro \
    989 	    /dev/${_drive}${_partition} /mnt2 ; then
    990 		echo "Cannot mount CD-ROM drive.  Aborting."
    991 		return
    992 	fi
    993 
    994 	install_from_mounted_fs /mnt2
    995 	umount -f /mnt2 > /dev/null 2>&1
    996 }
    997 
    998 mount_a_disk() {
    999 	# Mount a disk on /mnt2. The set of disk devices to choose from
   1000 	# is $_DKDEVS.
   1001 	# returns 0 on failure.
   1002 
   1003 	local _drive
   1004 	local _partition_range
   1005 	local _partition
   1006 	local _fstype
   1007 	local _fsopts
   1008 	local _directory
   1009 	local _md_fstype
   1010 	local _md_fsopts
   1011 
   1012 	getresp "abort"
   1013 	case "$resp" in
   1014 		abort)
   1015 			echo "Aborting."
   1016 			return 0
   1017 			;;
   1018 
   1019 		*)
   1020 			if isin $resp $_DKDEVS ; then
   1021 				_drive=$resp
   1022 			else
   1023 				echo ""
   1024 				echo "The disk $resp does not exist."
   1025 				echo "Aborting."
   1026 				return 0
   1027 			fi
   1028 			;;
   1029 	esac
   1030 
   1031 	# Get partition
   1032 	_partition_range=$(md_get_partition_range)
   1033 	resp=""		# force one iteration
   1034 	while [ -z "${resp}" ]; do
   1035 		echo -n "Partition? [d] "
   1036 		getresp "d"
   1037 		case "$resp" in
   1038 			$_partition_range)
   1039 				_partition=$resp
   1040 				;;
   1041 
   1042 			*)
   1043 				echo "Invalid response: $resp"
   1044 				resp=""		# force loop to repeat
   1045 				;;
   1046 		esac
   1047 	done
   1048 
   1049 	# Ask for filesystem type
   1050 	cat << \__mount_a_disk_2
   1051 
   1052 The following filesystem types are supported:
   1053 	1) ffs
   1054 	2) cd9660
   1055 __mount_a_disk_2
   1056 	_md_fstype=$(md_native_fstype)
   1057 	_md_fsopts=$(md_native_fsopts)
   1058 	if [ -n "$_md_fstype" ]; then
   1059 		echo "	3) $_md_fstype"
   1060 	else
   1061 		_md_fstype="_undefined_"
   1062 	fi
   1063 	resp=""		# force one iteration
   1064 	while [ -z "${resp}" ]; do
   1065 		echo -n "Which filesystem type? [ffs] "
   1066 		getresp "ffs"
   1067 		case "$resp" in
   1068 			ffs|cd9660)
   1069 				_fstype=$resp
   1070 				_fsopts="ro"
   1071 				;;
   1072 			$_md_fstype)
   1073 				_fstype=$resp
   1074 				_fsopts=$_md_fsopts
   1075 				;;
   1076 			*)
   1077 				echo "Invalid response: $resp"
   1078 				resp=""		# force loop to repeat
   1079 				;;
   1080 		esac
   1081 	done
   1082 
   1083 	# Mount the disk
   1084 	if ! mount -t ${_fstype} -o $_fsopts \
   1085 	    /dev/${_drive}${_partition} /mnt2 ; then
   1086 		echo "Cannot mount disk.  Aborting."
   1087 		return 0
   1088 	fi
   1089 	return 1
   1090 }
   1091 
   1092 install_disk() {
   1093 	local _directory
   1094 
   1095 	cat << \__install_disk_1
   1096 
   1097 Ok, lets install from a disk.  The file-system the install sets on may
   1098 already mounted, or we might have to mount the filesystem to get to it.
   1099 
   1100 __install_disk_1
   1101 
   1102 	echo -n "Is the file-system with the install sets already mounted? [n] "
   1103 	getresp "n"
   1104 	case $resp in
   1105 	y*|Y*)
   1106 		echo "What mount point are the sets located in? [] "
   1107 		getresp ""
   1108 		if [ -d "$resp" ]; then
   1109 			install_from_mounted_fs $resp
   1110 		else
   1111 			echo "$resp: Not a directory, aborting..."
   1112 		fi
   1113 		return
   1114 		;;
   1115 	*)
   1116 		;;
   1117 	esac
   1118 
   1119 	cat << \__install_disk_2
   1120 
   1121 The following disk devices are installed on your system; please select
   1122 the disk device containing the partition with the installation sets:
   1123 
   1124 __install_disk_2
   1125 	_DKDEVS=$(md_get_diskdevs)
   1126 	echo    "$_DKDEVS"
   1127 	echo	""
   1128 	echo -n	"Which is the disk with the installation sets? [abort] "
   1129 
   1130 	if mount_a_disk ; then
   1131 		return
   1132 	fi
   1133 
   1134 	install_from_mounted_fs /mnt2
   1135 	umount -f /mnt2 > /dev/null 2>&1
   1136 }
   1137 
   1138 install_nfs() {
   1139 	# Get the IP address of the server
   1140 	resp=""		# force one iteration
   1141 	while [ -z "${resp}" ]; do
   1142 		echo -n "Server IP address? [${_nfs_server_ip}] "
   1143 		getresp "${_nfs_server_ip}"
   1144 	done
   1145 	_nfs_server_ip=$resp
   1146 
   1147 	# Get server path to mount
   1148 	resp=""		# force one iteration
   1149 	while [ -z "${resp}" ]; do
   1150 		echo -n "Filesystem on server to mount? [${_nfs_server_path}] "
   1151 		getresp "${_nfs_server_path}"
   1152 	done
   1153 	_nfs_server_path=$resp
   1154 
   1155 	# Determine use of TCP
   1156 	echo -n "Use TCP transport (only works with capable NFS server)? [n] "
   1157 	getresp "n"
   1158 	case "$resp" in
   1159 		y*|Y*)
   1160 			_nfs_tcp="-T"
   1161 			;;
   1162 
   1163 		*)
   1164 			echo -n "Use small NFS transfers (needed when server "
   1165 			echo "or client"
   1166 			echo -n "has a slow network card)? [n] "
   1167 			getresp "n"
   1168 			case "$resp" in
   1169 			y*|Y*)
   1170 				_nfs_tcp="-r 1024 -w 1024"
   1171 				;;
   1172 
   1173 			*)
   1174 				_nfs_tcp=""
   1175 				;;
   1176 			esac
   1177 			;;
   1178 	esac
   1179 
   1180 	# Mount the server
   1181 	mkdir /mnt2 > /dev/null 2>&1
   1182 	if ! mount_nfs $_nfs_tcp ${_nfs_server_ip}:${_nfs_server_path} \
   1183 	    /mnt2 ; then
   1184 		echo "Cannot mount NFS server.  Aborting."
   1185 		return
   1186 	fi
   1187 
   1188 	install_from_mounted_fs /mnt2
   1189 	umount -f /mnt2 > /dev/null 2>&1
   1190 }
   1191 
   1192 install_tape() {
   1193 	local _xcmd
   1194 
   1195 	# Get the name of the tape from the user.
   1196 	cat << \__install_tape_1
   1197 
   1198 The installation program needs to know which tape device to use.  Make
   1199 sure you use a "no rewind on close" device.
   1200 
   1201 __install_tape_1
   1202 	_tape=$(basename $TAPE)
   1203 	resp=""		# force one iteration
   1204 	while [ -z "${resp}" ]; do
   1205 		echo -n "Name of tape device? [${_tape}]"
   1206 		getresp "${_tape}"
   1207 	done
   1208 	_tape=$(basename $resp)
   1209 	TAPE="/dev/${_tape}"
   1210 	if [ ! -c $TAPE ]; then
   1211 		echo "$TAPE does not exist or is not a character special file."
   1212 		echo "Aborting."
   1213 		return
   1214 	fi
   1215 	export TAPE
   1216 
   1217 	# Rewind the tape device
   1218 	echo -n "Rewinding tape..."
   1219 	if ! mt rewind ; then
   1220 		echo "$TAPE may not be attached to the system or may not be"
   1221 		echo "a tape device.  Aborting."
   1222 		return
   1223 	fi
   1224 	echo "done."
   1225 
   1226 	# Get the file number
   1227 	resp=""		# force one iteration
   1228 	while [ -z "${resp}" ]; do
   1229 		echo -n "File number? "
   1230 		getresp ""
   1231 		case "$resp" in
   1232 			[1-9]*)
   1233 				_nskip=$(expr $resp - 1)
   1234 				;;
   1235 
   1236 			*)
   1237 				echo "Invalid file number ${resp}."
   1238 				resp=""		# fore loop to repeat
   1239 				;;
   1240 		esac
   1241 	done
   1242 
   1243 	# Skip to correct file.
   1244 	echo -n "Skipping to source file..."
   1245 	if [ "${_nskip}" != "0" ]; then
   1246 		if ! mt fsf $_nskip ; then
   1247 			echo "Could not skip $_nskip files.  Aborting."
   1248 			return
   1249 		fi
   1250 	fi
   1251 	echo "done."
   1252 
   1253 	cat << \__install_tape_2
   1254 
   1255 There are 2 different ways the file can be stored on tape:
   1256 
   1257 	1) an image of a gzipped tar file
   1258 	2) a standard tar image
   1259 
   1260 __install_tape_2
   1261 	resp=""		# force one iteration
   1262 	while [ -z "${resp}" ]; do
   1263 		echo -n "Which way is it? [1] "
   1264 		getresp "1"
   1265 		case "$resp" in
   1266 		1)
   1267 			_xcmd="pax -zr${verbose_flag}pe"
   1268 			;;
   1269 
   1270 		2)
   1271 			_xcmd="pax -r${verbose_flag}pe"
   1272 			;;
   1273 
   1274 		*)
   1275 			echo "Invalid response: $resp."
   1276 			resp=""		# force loop to repeat
   1277 			;;
   1278 		esac
   1279 		( cd /mnt; dd if=$TAPE | $_xcmd )
   1280 	done
   1281 	echo "Extraction complete."
   1282 }
   1283 
   1284 get_timezone() {
   1285 	local _a
   1286 	local _zonepath
   1287 
   1288 	#
   1289 	# If the zoneinfo is not on the installation medium or on the
   1290 	# installed filesystem, set TZ to GMT and return immediatly.
   1291 	#
   1292 	if [ ! -e /usr/share/zoneinfo ] && [ ! -e /mnt/usr/share/zoneinfo ]; then
   1293 		TZ=GMT
   1294 		return
   1295 	fi
   1296 	if [ ! -d /usr/share/zoneinfo ]; then
   1297 		_zonepath=/mnt
   1298 	else
   1299 		_zonepath=""
   1300 	fi
   1301 		
   1302 cat << \__get_timezone_1
   1303 
   1304 Select a time zone for your location. Timezones are represented on the
   1305 system by a directory structure rooted in "/usr/share/zoneinfo". Most
   1306 timezones can be selected by entering a token like "MET" or "GMT-6".
   1307 Other zones are grouped by continent, with detailed zone information
   1308 separated by a slash ("/"), e.g. "US/Pacific".
   1309 
   1310 To get a listing of what's available in /usr/share/zoneinfo, enter "?"
   1311 at the prompts below.
   1312 
   1313 __get_timezone_1
   1314 	if [ -z "$TZ" ]; then
   1315 		TZ=$(ls -l /mnt/etc/localtime 2>/dev/null | cutlast)
   1316 		TZ=${TZ#/usr/share/zoneinfo/}
   1317 	fi
   1318 	while :; do
   1319 		echo -n	"What timezone are you in ['?' for list] [$TZ]? "
   1320 		getresp "$TZ"
   1321 		case "$resp" in
   1322 		"")
   1323 			echo "Timezone defaults to GMT"
   1324 			TZ="GMT"
   1325 			break;
   1326 			;;
   1327 		"?")
   1328 			ls ${_zonepath}/usr/share/zoneinfo
   1329 			;;
   1330 		*)
   1331 			_a=$resp
   1332 			while [ -d ${_zonepath}/usr/share/zoneinfo/$_a ]; do
   1333 				echo -n "There are several timezones available"
   1334 				echo " within zone '$_a'"
   1335 				echo -n "Select a sub-timezone ['?' for list]: "
   1336 				getresp ""
   1337 				case "$resp" in
   1338 				"?") ls ${_zonepath}/usr/share/zoneinfo/$_a ;;
   1339 				*)	_a=${_a}/${resp}
   1340 					if [ -f ${_zonepath}/usr/share/zoneinfo/$_a ]; then
   1341 						break;
   1342 					fi
   1343 					;;
   1344 				esac
   1345 			done
   1346 			if [ -f ${_zonepath}/usr/share/zoneinfo/$_a ]; then
   1347 				TZ="$_a"
   1348 				echo "You have selected timezone \"$_a\"".
   1349 				break 2
   1350 			fi
   1351 			echo "'/usr/share/zoneinfo/$_a' is not a valid timezone on this system."
   1352 			;;
   1353 		esac
   1354 	done
   1355 }
   1356 
   1357 install_sets()
   1358 {
   1359 	local _yup
   1360 	_yup="FALSE"
   1361 
   1362 	# Ask the user which media to load the distribution from.
   1363 	# Ask the user if they want verbose extraction.  They might not want
   1364 	# it on, eg, SPARC frame buffer console.
   1365 	cat << \__install_sets_1
   1366 
   1367 It is now time to extract the installation sets onto the hard disk.
   1368 Make sure the sets are either on a local device (i.e. tape, CD-ROM) or on a
   1369 network server.
   1370 
   1371 Would you like to see each file listed during extraction (verbose) mode?
   1372 On some console hardware, such as serial consoles and Sun frame buffers,
   1373 this can extend the total extraction time.
   1374 __install_sets_1
   1375 	echo -n "Use verbose listing for extractions? [y] "
   1376 	getresp "y"
   1377 	case "$resp" in
   1378 	y*|Y*)
   1379 		verbose_flag=v
   1380 		;;
   1381 	*)
   1382 		echo "Not using verbose listing."
   1383 		verbose_flag=""
   1384 		;;
   1385 	esac
   1386 
   1387 	if [ -d ${Default_sets_dir:-/dev/null} ]; then
   1388 		if dir_has_sets $Default_sets_dir $THESETS; then
   1389 			local_sets_dir=$Default_sets_dir
   1390 		fi
   1391 	fi
   1392 	if [ -n "${local_sets_dir}" ]; then
   1393 		install_from_mounted_fs ${local_sets_dir}
   1394 		if [ -n "$_setsdone" ]; then
   1395 			_yup="TRUE"
   1396 		fi
   1397 	fi
   1398 
   1399 	# Go on prodding for alternate locations
   1400 	resp=""		# force at least one iteration
   1401 	while [ -z "${resp}" ]; do
   1402 		# If _yup is not FALSE, it means that we extracted sets above.
   1403 		# If that's the case, bypass the menu the first time.
   1404 		if [ "${_yup}" = "FALSE" ]; then
   1405 			echo -n	"Install from (f)tp, (t)ape, (C)D-ROM, (N)FS"
   1406 			echo -n " or local (d)isk? "
   1407 			getresp ""
   1408 			case "$resp" in
   1409 			d*|D*)
   1410 				install_disk
   1411 				;;
   1412 			f*|F*)
   1413 				install_ftp
   1414 				;;
   1415 			t*|T*)
   1416 				install_tape
   1417 				;;
   1418 			c*|C*)
   1419 				install_cdrom
   1420 				;;
   1421 			n*|N*)
   1422 				install_nfs
   1423 				;;
   1424 			*)
   1425 				echo "Invalid response: $resp"
   1426 				resp=""
   1427 				;;
   1428 			esac
   1429 		else
   1430 			_yup="FALSE"	# So we'll ask next time
   1431 		fi
   1432 
   1433 		# Give the user the opportunity to extract more sets. They
   1434 		# don't necessarily have to come from the same media.
   1435 		echo	""
   1436 		echo -n	"Extract more sets? [n] "
   1437 		getresp "n"
   1438 		case "$resp" in
   1439 		y*|Y*)
   1440 			# Force loop to repeat
   1441 			resp=""
   1442 			;;
   1443 
   1444 		*)
   1445 			;;
   1446 		esac
   1447 	done
   1448 }
   1449 
   1450 munge_fstab()
   1451 {
   1452 	local _fstab
   1453 	local _fstab_shadow
   1454 	local _dev
   1455 	local _mp
   1456 	local _fstype
   1457 	local _rest
   1458 
   1459 	# Now that the 'real' fstab is configured, we munge it into a 'shadow'
   1460 	# fstab which we'll use for mounting and unmounting all of the target
   1461 	# filesystems relative to /mnt.  Mount all filesystems.
   1462 	_fstab=$1
   1463 	_fstab_shadow=$2
   1464 	( while read _dev _mp _fstype _rest; do
   1465 		# Skip comment lines
   1466 		case "$_dev" in
   1467 			\#*)	continue;;
   1468 			*)	;;
   1469 		esac
   1470 		# and some filesystem types (like there are swap,kernfs,...)
   1471 		case "$_fstype" in
   1472 			ffs|ufs|nfs)	;;
   1473 			*)	continue;;
   1474 		esac
   1475 		if [ "$_mp" = "/" ]; then
   1476 			echo $_dev /mnt $_fstype $_rest
   1477 		else
   1478 			echo $_dev /mnt$_mp $_fstype $_rest
   1479 		fi
   1480 	    done ) < $_fstab > $_fstab_shadow
   1481 }
   1482 
   1483 mount_fs()
   1484 {
   1485 	# Must mount filesystems manually, one at a time, so we can make
   1486 	# sure the mount points exist.
   1487 	# $1 is a file in fstab format
   1488 	local _fstab
   1489 
   1490 	_fstab=$1
   1491 
   1492 	( while read line; do
   1493 		set -- $line
   1494 		_dev=$1
   1495 		_mp=$2
   1496 		_fstype=$3
   1497 		_opt=$4
   1498 
   1499 		# If not the root filesystem, make sure the mount
   1500 		# point is present.
   1501 		if [ "$_mp" != "/mnt" ]; then
   1502 			mkdir -p $_mp
   1503 		fi
   1504 
   1505 		# Mount the filesystem.  If the mount fails, exit
   1506 		# with an error condition to tell the outer
   1507 		# later to bail.
   1508 		if ! mount -v -t $_fstype -o async -o $_opt $_dev $_mp ; then
   1509 			# error message displated by mount
   1510 			exit 1
   1511 		fi
   1512 	done ) < $_fstab
   1513 
   1514 	if [ "$?" != "0" ]; then
   1515 		cat << \__mount_filesystems_1
   1516 
   1517 FATAL ERROR:  Cannot mount filesystems.  Double-check your configuration
   1518 and restart the installation process.
   1519 __mount_filesystems_1
   1520 		exit
   1521 	fi
   1522 }
   1523 
   1524 unmount_fs()
   1525 {
   1526 	# Unmount all filesystems and check their integrity.
   1527 	# Usage: [-fast] <fstab file>
   1528 	local _fast
   1529 	local _fstab
   1530 	local _pid
   1531 
   1532 	if [ "$1" = "-fast" ]; then
   1533 		_fast=1
   1534 		_fstab=$2
   1535 	else
   1536 		_fast=0
   1537 		_fstab=$1
   1538 	fi
   1539 
   1540 	if ! [ -f "${_fstab}" ] || ! [ -s "${_fstab}" ]; then
   1541 		echo "fstab empty" > /dev/tty
   1542 		return
   1543 	fi
   1544 
   1545 	if [ $_fast = 0 ]; then
   1546 		echo -n	"Syncing disks..."
   1547 		_pid=$(twiddle)
   1548 		sync; sleep 4; sync; sleep 2; sync; sleep 2
   1549 		kill $_pid
   1550 		echo	"done."
   1551 	fi
   1552 
   1553 	(
   1554 		_devs=""
   1555 		_mps=""
   1556 		# maintain reverse order
   1557 		while read line; do
   1558 			set -- $line
   1559 			_devs="$1 ${_devs}"
   1560 			_mps="$2 ${_mps}"
   1561 		done
   1562 		echo -n "Umounting filesystems... "
   1563 		for _mp in ${_mps}; do
   1564 			echo -n "${_mp} "
   1565 			umount ${_mp}
   1566 		done
   1567 		echo "Done."
   1568 
   1569 		if [ $_fast = 0 ]; then
   1570 			exit
   1571 		fi
   1572 		echo "Checking filesystem integrity..."
   1573 		for _dev in ${_devs}; do
   1574 			echo  "${_dev}"
   1575 			fsck -f ${_dev}
   1576 		done
   1577 		echo "Done."
   1578 	) < $_fstab
   1579 }
   1580 
   1581 check_fs()
   1582 {
   1583 	# Check filesystem integrity.
   1584 	# $1 is a file in fstab format
   1585 	local _fstab
   1586 
   1587 	_fstab=$1
   1588 
   1589 	(
   1590 		_devs=""
   1591 		_mps=""
   1592 		while read line; do
   1593 			set -- $line
   1594 			_devs="$1 ${_devs}"
   1595 			_mps="$2 ${_mps}"
   1596 		done
   1597 
   1598 		echo "Checking filesystem integrity..."
   1599 		for _dev in ${_devs}; do
   1600 			echo  "${_dev}"
   1601 			fsck -f ${_dev}
   1602 		done
   1603 		echo "Done."
   1604 	) < $_fstab
   1605 }
   1606 
   1607 mi_mount_kernfs() {
   1608 	# Make sure kernfs is mounted.
   1609 	if [ ! -d /kern ] || [ ! -e /kern/msgbuf ]; then
   1610 		mkdir /kern > /dev/null 2>&1
   1611 		/sbin/mount_kernfs /kern /kern
   1612 	fi
   1613 }
   1614 
   1615 mi_filter_msgbuf() {
   1616 	# Remove timestemps, sort.
   1617 	sed -e 's/^\[[0-9. ]*\] //' < /kern/msgbuf | sort -u
   1618 }
   1619 
   1620 mi_filter_dmesg() {
   1621 	# Remove timestemps, sort.
   1622 	dmesg | awk '{ h=$0; gsub("^[[0-9. ]*] ", "", h); print h; }' \
   1623 	    | sort -u
   1624 }
   1625