Home | History | Annotate | Line # | Download | only in miniroot
      1 #!/bin/sh
      2 #	$NetBSD: install.sub,v 1.66 2024/05/11 06:31:59 andvar 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 modules rescue 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 success 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]*,,
    409 		s/--> [0-9.][0-9.]*//
    410 		s/netmask//
    411 		s/broadcast//
    412 		p;}')
    413 
    414 	_interface_ip=$1
    415 	_interface_mask=$2
    416 
    417 	# Get IP address
    418 	resp=""		# force one iteration
    419 	while [ -z "${resp}" ]; do
    420 		echo -n "IP address? [$_interface_ip] "
    421 		getresp "$_interface_ip"
    422 		_interface_ip=$resp
    423 	done
    424 
    425 	# Get symbolic name
    426 	resp=""		# force one iteration
    427 	while [ -z "${resp}" ]; do
    428 		echo -n "Symbolic (host) name? "
    429 		getresp ""
    430 		_interface_symname=$resp
    431 	done
    432 
    433 	# Get netmask
    434 	resp=""		# force one iteration
    435 	while [ -z "${resp}" ]; do
    436 		echo -n "Netmask? [$_interface_mask] "
    437 		getresp "$_interface_mask"
    438 		_interface_mask=$resp
    439 	done
    440 
    441 	echo "Your network interface might require explicit selection"
    442 	echo "of the type of network medium attached. Supported media:"
    443 	echo "$_interface_supported_media"
    444 	echo -n "Additional media type arguments (none)? [$_interface_mediumtype] "
    445 	getresp "$_interface_mediumtype"
    446 	_m=""
    447 	if [ "${resp:-none}" != "none" ]; then
    448 		_interface_mediumtype=$resp
    449 		_m="media ${resp}"
    450 	fi
    451 
    452 
    453 	echo "Your network interface might require additional link-layer"
    454 	echo "directives (like 'link0'). If this is the case you can enter"
    455 	echo "these at the next prompt."
    456 	echo ""
    457 	echo -n "Additional link-layer arguments (none)? [$_interface_extra] "
    458 	getresp "$_interface_extra"
    459 	if [ "${resp:-none}" != "none" ]; then
    460 		_interface_extra=$resp
    461 	fi
    462 
    463 	# Configure the interface.  If it
    464 	# succeeds, add it to the permanent
    465 	# network configuration info.
    466 	if [ $_up != "UP" ]; then
    467 		ifconfig ${_interface_name} down
    468 		if ifconfig ${_interface_name} inet \
    469 		    ${_interface_ip} \
    470 		    netmask ${_interface_mask} \
    471 		    ${_interface_extra} ${_m} up ; then
    472 			addifconfig \
    473 			    "${_interface_name}" \
    474 			    "${_interface_symname}" \
    475 			    "${_interface_ip}" \
    476 			    "${_interface_mask}" \
    477 			    "${_m}" \
    478 			    "${_interface_extra}"
    479 			return 0
    480 		fi
    481 	else
    482 		echo "Interface ${_interface_name} is already active."
    483 		echo "Just saving configuration on new root filesystem."
    484 		addifconfig \
    485 		    "${_interface_name}" \
    486 		    "${_interface_symname}" \
    487 		    "${_interface_ip}" \
    488 		    "${_interface_mask}" \
    489 		    "${_m}" \
    490 		    "${_interface_extra}"
    491 	fi
    492 	return 1
    493 }
    494 
    495 # Much of this is gratuitously stolen from /etc/rc.d/network.
    496 enable_network() {
    497 
    498 	# Set up the hostname.
    499 	if [ -f /mnt/etc/myname ]; then
    500 		hostname=$(cat /mnt/etc/myname)
    501 	elif [ -f /mnt/etc/rc.conf ];then
    502 		hostname=$(sh -c '. /mnt/etc/rc.conf ; echo $hostname')
    503 	else
    504 		echo "ERROR: no /etc/myname!"
    505 		return 1
    506 	fi
    507 	if [ -z "$hostname" ];then
    508 		echo "ERROR: hostname not set in /etc/myname or /etc/rc.conf!"
    509 		return 1
    510 	fi
    511 	hostname $hostname
    512 
    513 	# configure all the interfaces which we know about.
    514 if [ -f /mnt/etc/rc.conf ]; then
    515 (
    516 	# assume network interface configuration style 1.2D and up
    517 	if [ -f /mnt/etc/defaults/rc.conf ]; then
    518 		. /mnt/etc/defaults/rc.conf
    519 	fi
    520 	. /mnt/etc/rc.conf
    521 
    522 	if [ "$net_interfaces" != NO ]; then
    523 		if [ "$auto_ifconfig" = YES ]; then
    524 			tmp="$(ifconfig -l)"
    525 		else
    526 			tmp="$net_interfaces"
    527 		fi
    528 		echo -n "configuring network interfaces:"
    529 		for i in $tmp; do
    530 			eval $(echo 'args=$ifconfig_'$i)
    531 			if [ -n "$args" ]; then
    532 				echo -n " $i"
    533 				ifconfig $i $args
    534 			elif [ -f /mnt/etc/ifconfig.$i ]; then
    535 				echo -n " $i"
    536 				(while read args; do
    537 					ifconfig $i $args
    538 				done) < /mnt/etc/ifconfig.$i
    539 			elif [ "$auto_ifconfig" != YES ]; then
    540 				echo
    541 				echo -n "/mnt/etc/ifconfig.$i missing"
    542 				echo -n "& ifconfig_$i not set"
    543 				echo "; interface $i can't be configured"
    544 			fi
    545 		done
    546 		echo "."
    547 	fi
    548 )
    549 else
    550 (
    551 	tmp="$IFS"
    552 	IFS="$IFS."
    553 	set -- $(echo /mnt/etc/hostname*)
    554 	IFS=$tmp
    555 	unset tmp
    556 
    557 	while [ $# -ge 2 ] ; do
    558 		shift		# get rid of "hostname"
    559 		(
    560 			read af name mask bcaddr extras
    561 			read dt dtaddr
    562 
    563 			if [ -z "$name" ]; then
    564 		    echo "/etc/hostname.$1: invalid network configuration file"
    565 				exit
    566 			fi
    567 
    568 			cmd="ifconfig $1 $af $name "
    569 			if [ "${dt}" = "dest" ]; then cmd="$cmd $dtaddr"; fi
    570 			if [ -n "$mask" ]; then cmd="$cmd netmask $mask"; fi
    571 			if [ "${bcaddr:-NONE}" != "NONE" ]; then
    572 				cmd="$cmd broadcast $bcaddr";
    573 			fi
    574 			cmd="$cmd $extras"
    575 
    576 			$cmd
    577 		) < /mnt/etc/hostname.$1
    578 		shift
    579 	done
    580 )
    581 fi
    582 
    583 	# set the address for the loopback interface
    584 	ifconfig lo0 inet localhost
    585 
    586 	# use loopback, not the wire
    587 	route add $hostname localhost
    588 
    589 	# /etc/mygate, if it exists, contains the name of my gateway host
    590 	# that name must be in /etc/hosts.
    591 	if [ -f /mnt/etc/mygate ]; then
    592 		route delete default > /dev/null 2>&1
    593 		route add default $(cat /mnt/etc/mygate)
    594 	fi
    595 
    596 	# enable the resolver, if appropriate.
    597 	if [ -f /mnt/etc/resolv.conf ]; then
    598 		_resolver_enabled="TRUE"
    599 		cp /mnt/etc/resolv.conf /tmp/resolv.conf.shadow
    600 	fi
    601 
    602 	# Display results...
    603 	echo	"Network interface configuration:"
    604 	ifconfig -a
    605 
    606 	echo	""
    607 
    608 	if [ "${_resolver_enabled:-FALSE}" = "TRUE" ]; then
    609 		echo	"Resolver enabled."
    610 	else
    611 		echo	"Resolver not enabled."
    612 	fi
    613 
    614 	return 0
    615 }
    616 
    617 install_ftp() {
    618 	local	_f
    619 	local	_sets
    620 	local	_next
    621 
    622 	# Build a script to extract valid files from a list
    623 	# of filenames on stdin.
    624 	# XXX : Can we use this on more places? Leo.
    625 
    626 	echo "#!/bin/sh" > /tmp/fname_filter.sh
    627 	echo "while read line; do"	>> /tmp/fname_filter.sh
    628 	echo "    case \$line in"	>> /tmp/fname_filter.sh
    629 	for _f in $THESETS; do
    630 		echo "    $_f.tar.gz|$_f.tgz|$_f.tar|$_f.${VERSION}.aa)" \
    631 					>> /tmp/fname_filter.sh
    632 		echo '        echo -n "$line ";;' \
    633 					>> /tmp/fname_filter.sh
    634 	done
    635 	echo "        *) ;;"		>> /tmp/fname_filter.sh
    636 	echo "    esac"			>> /tmp/fname_filter.sh
    637 	echo "done"			>> /tmp/fname_filter.sh
    638 
    639 	# Get several parameters from the user, and create
    640 	# a shell script that directs the appropriate
    641 	# commands into ftp.
    642 	cat << \__install_ftp_1
    643 
    644 This is an automated ftp-based installation process.  You will be asked
    645 several questions.  The correct set of commands will be placed in a script
    646 that will be fed to ftp(1).
    647 
    648 __install_ftp_1
    649 	# Get server IP address
    650 	resp=""		# force one iteration
    651 	while [ -z "${resp}" ]; do
    652 		echo -n "Server IP? [${_ftp_server_ip}] "
    653 		getresp "${_ftp_server_ip}"
    654 		_ftp_server_ip=$resp
    655 	done
    656 
    657 	# Get login name
    658 	resp=""		# force one iteration
    659 	while [ -z "${resp}" ]; do
    660 		echo -n "Login? [${_ftp_server_login}] "
    661 		getresp "${_ftp_server_login}"
    662 		_ftp_server_login=$resp 
    663 	done
    664 
    665 	# Get password
    666 	resp=""		# force one iteration
    667 	while [ -z "${resp}" ]; do
    668 		echo -n "Password? "
    669 		stty -echo
    670 		getresp ""
    671 		echo ""
    672 		stty echo
    673 		_ftp_server_password=$resp
    674 	done
    675 
    676 	cat << \__install_ftp_2
    677 
    678 You will be asked to enter the name of the directory that contains the
    679 installation sets. When you enter a '?' you will see a listing of the
    680 current directory on the server.
    681 __install_ftp_2
    682 	echo ""
    683 	echo "The default installation directory in the official ftp server is:"
    684 	echo "/pub/NetBSD/NetBSD-${RELEASE}/${MACHINE}/binary/sets"
    685 
    686 	_sets=""
    687 	while [ -z "$_sets" ]
    688 	do
    689 		resp=""		# force one iteration
    690 		while [ -z "${resp}" ]; do
    691 			echo -n "Server directory? [${_ftp_server_dir}] "
    692 		    getresp "${_ftp_server_dir}"
    693 		    if [ -z "$resp" ] && [ -z "$_ftp_server_dir" ]; then
    694 			resp=""
    695 		    fi
    696 		done
    697 		if [ $resp != '?' ]; then
    698 			_ftp_server_dir=$resp
    699 		fi
    700 
    701 		# Build the basics of an ftp-script...
    702 		echo "#!/bin/sh" > /tmp/ftp-script.sh
    703 		echo "cd /mnt" >> /tmp/ftp-script.sh
    704 		echo "ftp -e -i -n $_ftp_server_ip << \__end_commands" >> \
    705 		    /tmp/ftp-script.sh
    706 		echo "user $_ftp_server_login $_ftp_server_password" >> \
    707 		    /tmp/ftp-script.sh
    708 		echo "bin" >> /tmp/ftp-script.sh
    709 		echo "cd $_ftp_server_dir" >> /tmp/ftp-script.sh
    710 
    711 		# Make a copy of this script that lists the directory
    712 		# contents, and use that to determine the files to get.
    713 		cat /tmp/ftp-script.sh	>  /tmp/ftp-dir.sh
    714 		echo "nlist"		>> /tmp/ftp-dir.sh
    715 		echo "quit"		>> /tmp/ftp-dir.sh
    716 		echo "__end_commands"	>> /tmp/ftp-dir.sh
    717 
    718 		if [ $resp = '?' ]; then
    719 			sh /tmp/ftp-dir.sh
    720 		else
    721 			_sets=$(sh /tmp/ftp-dir.sh | sort -u | sh /tmp/fname_filter.sh)
    722 		fi
    723 	done
    724 	rm -f /tmp/ftp-dir.sh /tmp/fname_filter.sh
    725 	rm -f /tmp/ftp-script.sh
    726 
    727 	# Prepare ftp-fetch script to fetch binary sets
    728 	_download_dir=INSTALL
    729 	_ftp_opts=""
    730 	_ftp_url="ftp://$_ftp_server_login:$_ftp_server_password@$_ftp_server_ip$_ftp_server_dir/"
    731 	echo "#!/bin/sh" > /tmp/ftp-fetch.sh
    732 	echo "cd /mnt" >> /tmp/ftp-fetch.sh
    733 	echo "mkdir -p $_download_dir" >> /tmp/ftp-fetch.sh
    734 
    735 	while : ; do
    736 		echo "The following sets are available for extraction:"
    737 		echo "(marked sets are already on the extraction list)"
    738 		echo ""
    739 
    740 		_next=""
    741 		for _f in $_sets ; do
    742 			if isin $_f $_setsdone; then
    743 				echo -n "[X] "
    744 				_next=""
    745 			else
    746 				echo -n "    "
    747 				if [ -z "$_next" ]; then _next=$_f; fi
    748 			fi
    749 			echo $_f
    750 		done
    751 		echo ""
    752 
    753 		# Get name of the file and add extraction command
    754 		# to the ftp-fetch script.
    755 		if [ -z "$_next" ]; then resp=n; else resp=y; fi
    756 		echo -n "Continue to add filenames [$resp]? "
    757 		getresp "$resp"
    758 		if [ "$resp" = "n" ]; then
    759 			break
    760 		fi
    761 
    762 		echo -n "File name [$_next]? "
    763 		getresp "$_next"
    764 		if isin $resp $_sets; then
    765 			echo "echo Fetching $resp:" >> \
    766 					/tmp/ftp-fetch.sh
    767 			echo "ftp ${_ftp_opts} -o $_download_dir/$resp ${_ftp_url}$resp" >> \
    768 					/tmp/ftp-fetch.sh
    769 			echo "echo Extracting $resp:" >> \
    770 					/tmp/ftp-fetch.sh
    771 			echo "pax -zr${verbose_flag}pe -f $_download_dir/$resp" >> \
    772 					/tmp/ftp-fetch.sh
    773 			echo "rm -f $_download_dir/$resp" >> \
    774 					/tmp/ftp-fetch.sh
    775 			_setsdone="$resp $_setsdone"
    776 		else
    777 			echo "You entered an invalid filename."
    778 			echo ""
    779 		fi
    780 	done
    781 
    782 	sh /tmp/ftp-fetch.sh
    783 	rm -f /tmp/ftp-fetch.sh
    784 	echo "Extraction complete."
    785 }
    786 
    787 install_from_mounted_fs() {
    788 	# $1 - directory containing installation sets
    789 	local _filename
    790 	local _sets
    791 	local _next
    792 	local _all
    793 	local _f
    794 	local _dirname
    795 
    796 	_dirname=$1
    797 	_sets=""
    798 
    799 	if ! dir_has_sets ${_dirname} $THESETS
    800 	then
    801 
    802 		echo ""
    803 		echo "The directory at the mount point, \"${_dirname}\", contains: "
    804 		echo ""
    805 		ls -F ${_dirname}
    806 		echo ""
    807 		echo    "Enter the subdirectory relative to the mountpoint, that"
    808 		echo -n "contains the savesets: [try this directory] "
    809 		getresp ""
    810 		if [ -n "${resp}" ]; then
    811 			_dirname=${_dirname}/$resp
    812 		fi
    813 
    814 		while ! dir_has_sets ${_dirname} $THESETS; do
    815 			echo ""
    816 			echo -n "There are no NetBSD install sets available in "
    817 			echo "\"${_dirname}\"."
    818 			echo "\"${_dirname}\" contains: "
    819 			echo ""
    820 			ls -F ${_dirname}
    821 			echo ""
    822 			echo -n "Enter subdirectory: [try other install media] "
    823 			getresp ""
    824 			if [ -z "${resp}" ]; then
    825 				return
    826 			fi
    827 			if [ ! -d ${_dirname}/${resp} ]; then
    828 				echo "\"${resp}\" is no directory; try again."
    829 			else
    830 				_dirname=${_dirname}/$resp
    831 			fi
    832 		done
    833 	fi
    834 
    835 	for _f in $THESETS ; do
    836 		if [ -f ${_dirname}/${_f}.tar.gz ]; then
    837 			_sets="$_sets ${_f}.tar.gz"
    838 		elif [ -f ${_dirname}/${_f}.tgz ]; then
    839 			_sets="$_sets ${_f}.tgz"
    840 		elif [ -f ${_dirname}/${_f}.tar ]; then
    841 			_sets="$_sets ${_f}.tar"
    842 		elif [ -f ${_dirname}/${_f}${VERSION}.aa ]; then
    843 			_sets="$_sets ${_f}${VERSION}"
    844 		fi
    845 	done
    846 
    847 	while : ; do
    848 		echo "The following sets are available for extraction:"
    849 		echo "(marked sets have already been extracted)"
    850 		echo ""
    851 
    852 		_next=""
    853 		_all=""
    854 		for _f in $_sets ; do
    855 			if isin $_f $_setsdone; then
    856 				echo -n "[X] "
    857 				_next=""
    858 			else
    859 				echo -n "    "
    860 				if [ -z "$_next" ]; then
    861 					_next=$_f;
    862 				fi
    863 				_all="$_all $_f"
    864 			fi
    865 			echo $_f
    866 		done
    867 		echo ""
    868 
    869 		# Get the name of the file.
    870 		if [ -z "$_next" ]; then
    871 			resp=n
    872 		else
    873 			resp=y
    874 		fi
    875 		echo -n "Continue extraction [$resp]?"
    876 		getresp "$resp"
    877 		if [ "$resp" = "n" ]; then
    878 			break
    879 		fi
    880 
    881 		echo -n "File name(s) (or "all") [$_next]? "
    882 		getresp "$_next"
    883 		if [ "x$resp" = xall ]; then
    884 			resp="$_all"
    885 		fi
    886 
    887 		for _f in $resp; do
    888 			_filename="/${_dirname}/$_f"
    889 
    890 			# Ensure file exists
    891 			if [ ! -f $_filename ]; then
    892 				if [ -f ${_filename}.aa ]; then
    893 					_filename=${_filename}.\?\?
    894 				else
    895 			 echo "File $_filename does not exist.  Check to make"
    896 			 echo "sure you entered the information properly."
    897 			 continue 2
    898 				fi
    899 			fi
    900 
    901 			# Extract file
    902 			echo "Extracting the $_f set:"
    903 			case "$_filename" in
    904 			*.tar)
    905 				(cd /mnt; pax -r${verbose_flag}pe < $_filename)
    906 				;;
    907 			*)
    908 				cat $_filename | \
    909 					(cd /mnt; pax -zr${verbose_flag}pe)
    910 				;;
    911 			esac
    912 			echo "Extraction complete."
    913 			_setsdone="$_f $_setsdone"
    914 		done
    915 
    916 	done
    917 }
    918 
    919 install_cdrom() {
    920 	local _drive
    921 	local _partition_range
    922 	local _partition
    923 	local _fstype
    924 	local _directory
    925 
    926 	# Get the cdrom device info
    927 	cat << \__install_cdrom_1
    928 
    929 The following CD-ROM devices are installed on your system; please select
    930 the CD-ROM device containing the partition with the installation sets:
    931 
    932 __install_cdrom_1
    933 	_CDDEVS=$(md_get_cddevs)
    934 	echo    "$_CDDEVS"
    935 	echo	""
    936 	echo -n	"Which is the CD-ROM with the installation media? [abort] "
    937 	getresp "abort"
    938 	case "$resp" in
    939 		abort)
    940 			echo "Aborting."
    941 			return
    942 			;;
    943 
    944 		*)
    945 			if isin $resp $_CDDEVS ; then
    946 				_drive=$resp
    947 			else
    948 				echo ""
    949 				echo "The CD-ROM $resp does not exist."
    950 				echo "Aborting."
    951 				return
    952 			fi
    953 			;;
    954 	esac
    955 
    956 	# Get partition
    957 	_partition_range=$(md_get_partition_range)
    958 	resp=""		# force one iteration
    959 	while [ -z "${resp}" ]; do
    960 		echo -n "Partition? [a] "
    961 		getresp "a"
    962 		case "$resp" in
    963 			$_partition_range)
    964 				_partition=$resp
    965 				;;
    966 
    967 			*)
    968 				echo "Invalid response: $resp"
    969 				resp=""		# force loop to repeat
    970 				;;
    971 		esac
    972 	done
    973 
    974 	# Ask for filesystem type
    975 	cat << \__install_cdrom_2
    976 
    977 There are two CD-ROM filesystem types currently supported by this program:
    978 	1) ISO-9660 (cd9660)
    979 	2) Berkeley Fast Filesystem (ffs)
    980 
    981 __install_cdrom_2
    982 	resp=""		# force one iteration
    983 	while [ -z "${resp}" ]; do
    984 		echo -n "Which filesystem type? [cd9660] "
    985 		getresp "cd9660"
    986 		case "$resp" in
    987 			cd9660|ffs)
    988 				_fstype=$resp
    989 				;;
    990 
    991 			*)
    992 				echo "Invalid response: $resp"
    993 				resp=""		# force loop to repeat
    994 				;;
    995 		esac
    996 	done
    997 
    998 	# Mount the CD-ROM
    999 	if ! mount -t ${_fstype} -o ro \
   1000 	    /dev/${_drive}${_partition} /mnt2 ; then
   1001 		echo "Cannot mount CD-ROM drive.  Aborting."
   1002 		return
   1003 	fi
   1004 
   1005 	install_from_mounted_fs /mnt2
   1006 	umount -f /mnt2 > /dev/null 2>&1
   1007 }
   1008 
   1009 mount_a_disk() {
   1010 	# Mount a disk on /mnt2. The set of disk devices to choose from
   1011 	# is $_DKDEVS.
   1012 	# returns 0 on failure.
   1013 
   1014 	local _drive
   1015 	local _partition_range
   1016 	local _partition
   1017 	local _fstype
   1018 	local _fsopts
   1019 	local _directory
   1020 	local _md_fstype
   1021 	local _md_fsopts
   1022 
   1023 	getresp "abort"
   1024 	case "$resp" in
   1025 		abort)
   1026 			echo "Aborting."
   1027 			return 0
   1028 			;;
   1029 
   1030 		*)
   1031 			if isin $resp $_DKDEVS ; then
   1032 				_drive=$resp
   1033 			else
   1034 				echo ""
   1035 				echo "The disk $resp does not exist."
   1036 				echo "Aborting."
   1037 				return 0
   1038 			fi
   1039 			;;
   1040 	esac
   1041 
   1042 	# Get partition
   1043 	_partition_range=$(md_get_partition_range)
   1044 	resp=""		# force one iteration
   1045 	while [ -z "${resp}" ]; do
   1046 		echo -n "Partition? [d] "
   1047 		getresp "d"
   1048 		case "$resp" in
   1049 			$_partition_range)
   1050 				_partition=$resp
   1051 				;;
   1052 
   1053 			*)
   1054 				echo "Invalid response: $resp"
   1055 				resp=""		# force loop to repeat
   1056 				;;
   1057 		esac
   1058 	done
   1059 
   1060 	# Ask for filesystem type
   1061 	cat << \__mount_a_disk_2
   1062 
   1063 The following filesystem types are supported:
   1064 	1) ffs
   1065 	2) cd9660
   1066 __mount_a_disk_2
   1067 	_md_fstype=$(md_native_fstype)
   1068 	_md_fsopts=$(md_native_fsopts)
   1069 	if [ -n "$_md_fstype" ]; then
   1070 		echo "	3) $_md_fstype"
   1071 	else
   1072 		_md_fstype="_undefined_"
   1073 	fi
   1074 	resp=""		# force one iteration
   1075 	while [ -z "${resp}" ]; do
   1076 		echo -n "Which filesystem type? [ffs] "
   1077 		getresp "ffs"
   1078 		case "$resp" in
   1079 			ffs|cd9660)
   1080 				_fstype=$resp
   1081 				_fsopts="ro"
   1082 				;;
   1083 			$_md_fstype)
   1084 				_fstype=$resp
   1085 				_fsopts=$_md_fsopts
   1086 				;;
   1087 			*)
   1088 				echo "Invalid response: $resp"
   1089 				resp=""		# force loop to repeat
   1090 				;;
   1091 		esac
   1092 	done
   1093 
   1094 	# Mount the disk
   1095 	if ! mount -t ${_fstype} -o $_fsopts \
   1096 	    /dev/${_drive}${_partition} /mnt2 ; then
   1097 		echo "Cannot mount disk.  Aborting."
   1098 		return 0
   1099 	fi
   1100 	return 1
   1101 }
   1102 
   1103 install_disk() {
   1104 	local _directory
   1105 
   1106 	cat << \__install_disk_1
   1107 
   1108 Ok, lets install from a disk.  The file-system the install sets on may
   1109 already mounted, or we might have to mount the filesystem to get to it.
   1110 
   1111 __install_disk_1
   1112 
   1113 	echo -n "Is the file-system with the install sets already mounted? [n] "
   1114 	getresp "n"
   1115 	case $resp in
   1116 	y*|Y*)
   1117 		echo "What mount point are the sets located in? [] "
   1118 		getresp ""
   1119 		if [ -d "$resp" ]; then
   1120 			install_from_mounted_fs $resp
   1121 		else
   1122 			echo "$resp: Not a directory, aborting..."
   1123 		fi
   1124 		return
   1125 		;;
   1126 	*)
   1127 		;;
   1128 	esac
   1129 
   1130 	cat << \__install_disk_2
   1131 
   1132 The following disk devices are installed on your system; please select
   1133 the disk device containing the partition with the installation sets:
   1134 
   1135 __install_disk_2
   1136 	_DKDEVS=$(md_get_diskdevs)
   1137 	echo    "$_DKDEVS"
   1138 	echo	""
   1139 	echo -n	"Which is the disk with the installation sets? [abort] "
   1140 
   1141 	if mount_a_disk ; then
   1142 		return
   1143 	fi
   1144 
   1145 	install_from_mounted_fs /mnt2
   1146 	umount -f /mnt2 > /dev/null 2>&1
   1147 }
   1148 
   1149 install_nfs() {
   1150 	# Get the IP address of the server
   1151 	resp=""		# force one iteration
   1152 	while [ -z "${resp}" ]; do
   1153 		echo -n "Server IP address? [${_nfs_server_ip}] "
   1154 		getresp "${_nfs_server_ip}"
   1155 	done
   1156 	_nfs_server_ip=$resp
   1157 
   1158 	# Get server path to mount
   1159 	resp=""		# force one iteration
   1160 	while [ -z "${resp}" ]; do
   1161 		echo -n "Filesystem on server to mount? [${_nfs_server_path}] "
   1162 		getresp "${_nfs_server_path}"
   1163 	done
   1164 	_nfs_server_path=$resp
   1165 
   1166 	# Check mount_nfs(8) options
   1167 	echo "Use small NFS transfers (needed when server or client"
   1168 	echo -n "has a slow network card)? [n] "
   1169 	getresp "n"
   1170 	case "$resp" in
   1171 		y*|Y*)
   1172 			_nfs_tcp="-r 1024 -w 1024"
   1173 			;;
   1174 
   1175 		*)
   1176 			_nfs_tcp=""
   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 immediately.
   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 displayed 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 "Unmounting 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 timestamps, sort.
   1617 	sed -e 's/^\[[0-9. ]*\] //' < /kern/msgbuf | sort -u
   1618 }
   1619 
   1620 mi_filter_dmesg() {
   1621 	# Remove timestamps, sort.
   1622 	dmesg | awk '{ h=$0; gsub("^[[0-9. ]*] ", "", h); print h; }' \
   1623 	    | sort -u
   1624 }
   1625