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