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