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