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