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