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