# $MirOS: src/distrib/common/install.sub,v 1.70 2014/03/30 11:03:32 tg Exp $ # $OpenBSD: install.sub,v 1.388 2005/07/02 00:55:48 uwe Exp $ # $NetBSD: install.sub,v 1.5.2.8 1996/09/02 23:25:02 pk Exp $ # # Copyright (c) 2003, 2004, 2005, 2008, 2009, 2010, 2011, 2013, 2014 # Thorsten “mirabilos” Glaser # Copyright (c) 1997-2005 Todd Miller, Theo de Raadt, Ken Westerback # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Copyright (c) 1996 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by Jason R. Thorpe. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the NetBSD # Foundation, Inc. and its contributors. # 4. Neither the name of The NetBSD Foundation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # MirBSD install/upgrade script common subroutines and initialization code # Include machine-dependent functions and definitions. # # The following functions must be provided: # md_congrats() - display friendly message # md_prep_disklabel() - put an OpenBSD disklabel on the disk # # The following variables can be provided if required: # MDSETS - list of files to add to THESETS # MDFSTYPE - nothing assumed if not provided # MDFSOPTS - nothing assumed if not provided # MDDKDEVS - '/^r*a*[swi]d[0-9][0-9]* /s/ .*//p' assumed if not provided # MDCDDEVS - '/^cd[0-9][0-9]* /s/ .*//p' assumed if not provided # MDMTDEVS - '/^[cmsw]t[0-9][0-9]* /s/ .*//p' # MDXAPERTURE - set machdep.allowaperture=value in sysctl.conf . /etc/functions . install.md if _vbox_check; then echo Sorry, WirrtualBox is not supported. echo To continue on your own risk: ':>/allow-vbox' echo But remember that vbox is buggy and often broken! test -e /allow-vbox || exit 1 fi set_term() { typeset TERMS=vt100,vt220,wsvtg,wsvt25,dumb echo "Possible types: $TERMS" ask "Terminal type?" ${TERM:-vt220} TERM=$resp export TERM [[ -x /sbin/kbd ]] || return while :; do ask "kbd(8) mapping? ('?' for list)" "none" [[ $resp = none ]] && return [[ $resp = @(\?|+([0-9])) && -z ${layouts[0]} ]] && \ set -A layouts -- $(kbd -lq | \ egrep '^..\.?(nodead|dvorak)?$' | sort) [[ $resp = +([0-9]) ]] && resp=${layouts[$resp]} [[ $resp = [a-z]* ]] && if kbd $resp; then echo $resp >/tmp/kbdtype return fi [[ $resp = \? ]] || continue print Available keyboard mappings: typeset -iR3 i=0 while (( i < ${#layouts[*]} )); do print "$i) ${layouts[i]}" let i++ done | rs done } welcome() { typeset _q cat <<__EOT Welcome to the ${OBSD} $MODE program (old, rewrite in progress). This programme will help you $MODE MirOS. At any prompt except password prompts you can run a shell command by typing '!foo', or escape to a shell by typing '!'. Default answers are shown in []s and are selected by just RETURN, but sometimes there is no default. At any time you can exit this programme by pressing Control-C and then RETURN, but quitting during an $MODE can leave your system in an inconsistent state. __EOT # Configure the terminal and keyboard. set_term cat <<__EOT IS YOUR DATA BACKED UP? As with anything that modifies disk contents, this program can cause SIGNIFICANT data loss. __EOT case $MODE in upgrade) cat <<__EOT NOTE: before your system has been upgraded, you must manually merge any changes to files in the 'etc' and 'xetc' sets into the files already on your system. __EOT _q="Proceed with upgrade?" ;; install) cat <<__EOT It is often helpful to have the installation notes handy. For complex disk configurations, relevant disk hardware manuals and a calculator are useful. __EOT if [ -f /etc/fstab ]; then cat <<__EOT You seem to be trying to restart an interrupted installation! You can skip the disk preparation steps and continue, or you can reboot and start over. __EOT _q="Skip disk initialization?" else _q="Proceed with install?" fi ;; esac ask_yn "$_q" if [[ $resp = n ]]; then cat <<__EOT Enter 'halt -p' or 'reboot' at the prompt to gracefully exit MirBSD. You can then power cycle the machine and boot BSD or your other OSes. __EOT exit fi echo "Cool! Let's get to it." } scan_dmesg() { bsort $(sed -ne "$1" /var/run/dmesg.boot) } # Get the first (lowest unit #) serial device if any, if MDSERIAL is set. # NOTE: Only single digit serial devices (0 -> 9) are looked for. get_serialdev() { typeset _d _bd [[ -n $MDSERIAL ]] || exit set -- $MDSERIAL _d=$1 _bd=$2 set -- $(scan_dmesg "/^${_d}\([0-9]\) .*/s//\1/p") [[ -z $1 ]] || echo "$_bd$1" } get_drive() { ask_which "$1" "contains the $MODE media" "$2" [[ $resp = done ]] && return 1 makedev $resp || return 1 return 0 } get_partition() { typeset _drive=$1 _fstypes=$2 _part _fst # Create file /tmp/parts.$_drive where each line is of the # form " ". disklabel $_drive 2>/dev/null \ | grep '^ [a-p]: ' \ | egrep -v "swap|unused" \ | sed -e 's/^ \(.\): *[^ ]* *[^ ]* *\([^ ]*\) .*/\1 \2/' \ >/tmp/parts.$_drive disklabel $_drive 2>/dev/null | grep '^ .:' ask_which "$_drive partition" "has the $MODE sets" \ "$(sed -e 's/^\(.\).*/\1/' /tmp/parts.$_drive)" [[ $resp = done ]] && return 1 _part=$resp _fst=$(sed -ne "/^$_part /s///p" /tmp/parts.$_drive) ask_which "filesystem type" "should be used to mount $_drive$_part" "$_fst $_fstypes ffs" case $resp in done) return 1 ;; $_fst) resp="$_part" ;; *) resp="$_part $resp" ;; esac return 0 } # Ask for a password, saving the input in $resp. # Display $1 as the prompt. # *Don't* allow the '!' options that ask does. # *Don't* echo input. askpass() { set -o noglob stty -echo read resp?"$1 " stty echo set +o noglob echo } # Ask for user input. # # $1 = the question to ask the user # $2 = the default answer # # Save the user input (or the default) in $resp. # # Allow the user to escape to shells ('!') or execute commands # ('!foo') before entering the input. ask() { typeset _question=$1 _default=$2 set -o noglob while :; do echo -n "$_question " [[ -z $_default ]] || echo -n "[$_default] " read resp case $resp in !) echo "Type 'exit' to return to install." sh ;; !*) eval ${resp#?} ;; *) : ${resp:=$_default} break ;; esac done set +o noglob } # Ask for user input until a non-empty reply is entered. # # $1 = the question to ask the user # $2 = the default answer # # Save the user input (or the default) in $resp. ask_until() { resp= while [[ -z $resp ]]; do ask "$1" "$2" done } # Ask the user for a y or n, and insist on 'y', 'yes', 'n' or 'no'. # # $1 = the question to ask the user # $2 = the default answer (assumed to be 'n' if empty). # # Return 'y' or 'n' in $resp. ask_yn() { typeset _q=$1 _a=${2:-no} _resp typeset -l _resp while :; do ask "$_q" "$_a" _resp=$resp case $_resp in y|yes) resp=y; return ;; n|no) resp=n; return ;; esac done } # Ask for the user to select one value from a list, or 'done'. # # $1 = name of the list items (disk, cd, etc.) # $2 = question to ask # $3 = list of valid choices # $4 = default choice, if it is not specified use the first item in $3 # $5 = error message if no items in $3, defaults to 'No $1s found.' # # At exit $resp holds selected item, or 'done' ask_which() { typeset _name=$1 _query=$2 _list=$3 _def=$4 _err=$5 set -- $_list if (( $# < 1 )); then echo "${_err:=No ${_name}s found}." resp=done return fi : ${_def:=$1} # Eliminate extraneous (especially trailing) whitespace in _list. _list="$*" while :; do # Put both lines in ask prompt, rather than use a # separate 'echo' to ensure the entire question is # re-ask'ed after a '!' or '!foo' shell escape. ask "Available ${_name}s are: $_list.\nWhich one $_query? (or 'done')" "$_def" # Quote $resp to prevent user from confusing isin() by # entering something like 'a a'. isin "$resp" $_list done && break echo "'$resp' is not a valid choice." done } # test the first argument against the remaining ones, return success on a match isin() { typeset _a=$1 _b shift for _b; do [[ $_a = $_b ]] && return 0 done return 1 } # add first argument to list formed by the remaining arguments # adds to the tail if the element does not already exist addel() { typeset _a=$1 shift echo -n "$*" isin "$_a" $* || echo -n " $_a" } # remove all occurrences of first argument from list formed by # the remaining arguments rmel() { typeset _a=$1 _b shift for _b; do [[ $_a != $_b ]] && echo -n "$_b " done } bsort() { typeset _l _a=$1 _b (( $# > 0 )) || return shift for _b; do if [[ $_a != $_b ]]; then if [[ $_a >$_b ]]; then _l="$_a $_l"; _a=$_b else _l="$_b $_l" fi fi done # Output the smallest value found. echo -n "$_a " # Sort remaining values. bsort $_l } # Add interesting/useful comments from mnt/etc/$1 to /tmp/$1. # # $1 == file in /tmp and /mnt/etc directories save_comments() { typeset _file=$1 if [[ -f /mnt/etc/$_file ]]; then grep "^#" /mnt/etc/$_file >/tmp/$_file.new [[ -f /tmp/$_file ]] && cat /tmp/$_file >>/tmp/$_file.new mv /tmp/$_file.new /tmp/$_file fi } # Offer to edit a file in /tmp and execute ${EDITOR} to do so if the user # accepts the offer. # # $1 == file in /tmp to edit edit_tmp_file() { typeset _file=$1 ask_yn "Edit $_file with $EDITOR?" [[ $resp = y ]] && $EDITOR /tmp/$_file } # Offer to shell out for manual network configuration, and do so if # the user accepts the offer. manual_net_cfg() { typeset _x ask_yn "Do you want to do any manual network configuration?" [[ $resp = y ]] && { echo "Type 'exit' to return to $MODE."; sh; } # the network is now up… pf=https ftp -h 2>&1 | fgrep https >/dev/null 2>&1 || pf=http _getrnd net $pf _ntp } # log in via ftp to host $1 as user $2 with password $3 # and return a list of all files in the directory $4 on stdout ftp_list_files() { ftp ${_ftp_active} -V -n "$1" <<__EOT user "$2" "$3" cd "$4" ls quit __EOT } # Create a device. # # $1 = name of the device to create. makedev() { typeset _dev=$1 if [[ ! -r /dev/MAKEDEV ]]; then echo "MAKEDEV not found. Can't create device nodes." return 1 fi cd /dev; mksh MAKEDEV $_dev || return 1 ; cd - >/dev/null } # Create an entry in the hosts file. If an entry with the # same symbolic name and address family already exists, delete it. # $1 - IP address (v6 if it contains ':', else v4) # $2 - symbolic name addhostent() { typeset _addr=$1 _name=$2 _leader if [[ $_addr = *:* ]]; then _leader='/^[0-9a-fA-F]*:' else _leader='/^[0-9]*\.' fi sed "${_leader}.*[ ]$_name\$/d" /tmp/hosts >/tmp/hosts.new echo "$_addr $_name" >>/tmp/hosts.new mv /tmp/hosts.new /tmp/hosts } # Show list of available sets and let the user select which sets to install. # # $1 = available sets # $2 = already selected sets # # Set $resp to list of selected sets. select_sets() { typeset _avail=$1 _selected=$2 _next _f _action cat <<__EOT Select sets by entering a set name, a file name pattern or 'all'. De-select sets by prepending a '-' to the set name, file name pattern or 'all'. Selected sets are labelled '[x]'. __EOT while :; do _action= _next= echo for _f in $_avail; do if isin $_f $_selected; then echo " [X] $_f" else echo " [ ] $_f" : ${_next:=$_f} fi done : ${_next:=done} ask "Set name? (or 'done')" "$_next" case $resp in done) break ;; -*) _action=rmel ;; esac : ${_action:=addel} resp=${resp#+|-} case $resp in "") continue ;; all) resp=* ;; esac # Use @($resp) rather than just $resp to protect # against silly user input that might cause syntax # errors. for _f in $_avail; do eval "case $_f in @($resp)) _selected=\`$_action $_f \$_selected\` ;; esac" done done resp=$_selected } configure_ifs() { typeset _IFDEVS=$(ifconfig -l) _ifs _name _media _hn while :; do ask_which "interface" "do you wish to initialise" "$_IFDEVS" \ "" "No more interfaces to initialise" [[ $resp = done ]] && break _ifs=$resp _hn=/tmp/hostname.$_ifs # Get symbolic name - will be used in DHCP requests. ask "Symbolic (host) name for $_ifs?" "$(hostname -s)" _name=$resp # Get and apply media options. _media=$(ifconfig -m $_ifs | grep "media ") if [[ -n $_media ]]; then cat <<__EOT The media options for $_ifs are currently $(ifconfig -m $_ifs | sed -n '/supported/D;/media:/p') __EOT ask_yn "Do you want to change the media options?" case $resp in y) cat <<__EOT Supported media options for $_ifs are: $_media __EOT ask "Media options for $_ifs?" _media=$resp ifconfig $_ifs $_media || return 1 ;; n) _media= ;; esac fi rm -f $_hn v4_config "$_ifs" "$_media" "$_name" "$_hn" v6_config "$_ifs" "$_media" "$_name" "$_hn" [[ -f $_hn ]] && _IFDEVS=$(rmel "$_ifs" $_IFDEVS) done } # Output ' [ ]'. # # $1 == interface v4_info() { ifconfig $1 inet | sed -n ' 1s/.* '. # # $1 == interface v6_info() { ifconfig $1 inet6 | sed -n ' 1s/.*/etc/resolv.conf.tail if [[ -n $_hn ]]; then _hn="send host-name \"$_hn\";" echo "Issuing hostname-associated DHCP request for $_ifs." else echo "Issuing free-roaming DHCP request for $_ifs." fi cat >/etc/dhclient.conf <<__EOT initial-interval 1; $_hn request subnet-mask, broadcast-address, routers, domain-name, domain-name-servers, host-name; __EOT dhclient $_ifs set -- $(v4_info $_ifs) if [[ $1 = UP && -n $2 ]]; then # Move configuration files to where they will be copied to the # installed system. Overwrites configuration information from # last successful dhcp attempt. mv /etc/dhclient.conf /tmp/dhclient.conf mv /etc/resolv.conf.tail /tmp/resolv.conf.tail return 0 fi ifconfig $_ifs delete down rm /etc/dhclient.conf /etc/resolv.conf.tail return 1 } v4_config() { typeset _ifs=$1 _media=$2 _name=$3 _hn=$4 _prompt set -- $(v4_info $_ifs) if [[ -n $2 ]]; then ifconfig $_ifs inet $2 delete [[ $2 != "0.0.0.0" ]] && { _addr=$2; _mask=$3; } fi [[ -x /sbin/dhclient ]] && _prompt=" or 'dhcp'" _prompt="IPv4 address for $_ifs? (or 'none'$_prompt)" ask_until "$_prompt" "$_addr" case $resp in none) ;; dhcp) if [[ ! -x /sbin/dhclient ]]; then echo "DHCP not possible - no /sbin/dhclient." elif dhcp_request $_ifs "$_name" || dhcp_request $_ifs ; then addhostent "127.0.0.1" "$_name" echo "dhcp NONE NONE NONE $_media" >>$_hn dhcp_requested=", 'dhcp'" fi ;; *) _addr=$resp ask_until "Netmask?" "${_mask:=255.255.255.0}" if ifconfig $_ifs inet $_addr netmask $resp up ; then addhostent "$_addr" "$_name" echo "inet $_addr $resp NONE $_media" >$_hn fi ;; esac } v6_config() { typeset _ifs=$1 _media=$2 _name=$3 _hn=$4 _addr _prefixlen _prompt _eui ifconfig lo0 inet6 >/dev/null 2>&1 || return set -- $(v6_info $_ifs) [[ -n $2 ]] && { _addr=$2; _prefixlen=$3; } [[ -x /sbin/rtsol ]] && _prompt="or 'rtsol' " echo To append EUI64 automatically, let the address end with two colons. _prompt="IPv6 address for $_ifs? (${_prompt}or 'none')" ask_until "$_prompt" "${_addr:-none}" case $resp in none) return ;; rtsol) [[ ! -x /sbin/rtsol ]] && { echo "No /sbin/rtsol." ; return ; } sysctl -w net.inet6.ip6.accept_rtadv=1 ifconfig $_ifs up rtsol $_ifs addhostent "::1" "$_name" echo "up\nrtsol $media" >>$_hn return ;; *::) _eui=eui64 ;; esac _addr=$resp ask_until "IPv6 prefix length for $_ifs?" "${_prefixlen:=64}" ifconfig $_ifs inet6 $_addr prefixlen $resp $_eui up || return echo inet6 $_addr $resp $_eui $media >>$_hn if [[ -n $_eui ]]; then set -- $(v6_info $_ifs) [[ -n $2 ]] && _addr=$2 fi addhostent "$_addr" "$_name" v6_defroute $_ifs [[ $resp = none ]] && return route -n add -inet6 default "$resp" || return echo "route add -inet6 default $resp" >>$_hn } v4_defroute() { typeset _dr _fls _prompt=" or 'none'" _prompt="Default IPv4 route? (IPv4 address$dhcp_requested$_prompt)" _dr=$(route -n show -inet | sed -ne '/^default */{s///; s/ .*//; p;}') [[ -f /tmp/dhclient.conf ]] && _dr=dhcp while :; do ask_until "$_prompt" "$_dr" [[ $resp = @(none|dhcp) ]] && break route -n delete -inet default >/dev/null 2>&1 route -n add -inet default "$resp" && { set -A _fls -- /tmp/hostname.* (( ${#_fls[*]} == 1 )) || _fls=/tmp/hostname.local echo "route add -inet default $resp" >>$_fls break } # Put the old default route back. The new one did not work. route -n add -inet default $_dr >/dev/null 2>&1 done } v6_defroute() { typeset _if=$1 _routers _oifs if [[ -n $(route -n show -inet6 | sed -ne '/^default */{s///; s/ .*//; p;}') ]]; then resp=none return fi if [[ -x /sbin/ping6 ]]; then _routers=$(ping6 -n -c 2 ff02::2%$_if 2>&1 | sed -n \ -e '/bytes from/{s/^.*from //;s/,.*$//;p;}') fi _oifs=$IFS IFS= PS3="IPv6 default router? (list #, IPv6 address or 'none'): " select i in $_routers; do case $i in "") resp=$REPLY [[ -n $resp ]] && break ;; *) resp=$i break ;; esac done IFS=$_oifs } # Much of this is gratuitously stolen from /etc/netstart. enable_network() { typeset _netfile # Copy any required or optional files found for _netfile in hosts dhclient.conf resolv.conf resolv.conf.tail protocols services; do if [ -f /mnt/etc/${_netfile} ]; then cp /mnt/etc/${_netfile} /etc/${_netfile} fi done # Set the address for the loopback interface. Bringing the # interface up, automatically invokes the IPv6 address ::1. ifconfig lo0 inet 127.0.0.1 # configure all of the non-loopback interfaces which we know about. # refer to hostname.if(5) for hn in /mnt/etc/hostname.*; do # Strip off /mnt/etc/hostname. prefix if=${hn#/mnt/etc/hostname.} # Check for ifconfig'able interface. ifconfig $if >/dev/null 2>&1 || continue # Now parse the hostname.* file while :; do if [ "$cmd2" ]; then # we are carrying over from the # 'read dt dtaddr' last time set -A i -- $cmd2 af=${i[0]} name=${i[1]} mask=${i[2]} bcaddr=${i[3]} ext1=${i[4]} unset i[0] i[1] i[2] i[3] i[4] ext2="${i[*]}" cmd2= else # read the next line or exit the while loop read af name mask bcaddr ext1 ext2 || break fi # $af can be "dhcp", "up", "rtsol", an address family, commands, or # a comment. case $af in "route"|"!route") routep="-n $name" [ x"$name" = x"+n" ] && routep= cmd="/sbin/route ${routep} ${mask} ${bcaddr} ${ext1} ${ext2}" ;; "#"*|"!"*|"bridge"|"") # skip comments, user commands, bridges, # and empty lines continue ;; "dhcp") [ "$name" = "NONE" ] && name= [ "$mask" = "NONE" ] && mask= [ "$bcaddr" = "NONE" ] && bcaddr= ifconfig $if $name $mask $bcaddr $ext1 $ext2 down cmd="dhclient $if" ;; "rtsol") ifconfig $if $name $mask $bcaddr $ext1 $ext2 up rtsif="$rtsif $if" cmd= ;; "up") # The only one of these guaranteed to be set is $if # the remaining ones exist so that media controls work cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up" ;; *) read dt dtaddr if [ "$name" = "alias" ]; then # perform a 'shift' of sorts alias=$name name=$mask mask=$bcaddr bcaddr=$ext1 ext1=$ext2 ext2= else alias= fi cmd="ifconfig $if $af $alias $name " case $dt in dest) cmd="$cmd $dtaddr" ;; [a-z!]*) cmd2="$dt $dtaddr" ;; esac if [ ! -n "$name" ]; then echo "/mnt/etc/hostname.$if: invalid network configuration file" return fi case $af in inet) [ "$mask" ] && cmd="$cmd netmask $mask" if [ "$bcaddr" -a "$bcaddr" != "NONE" ]; then cmd="$cmd broadcast $bcaddr" fi [ "$alias" ] && rtcmd="; route -qn add -host $name 127.0.0.1" ;; inet6) [ "$mask" ] && cmd="$cmd prefixlen $mask" cmd="$cmd $bcaddr" ;; *) cmd="$cmd $mask $bcaddr" esac cmd="$cmd $ext1 $ext2$rtcmd" rtcmd= ;; esac eval "$cmd" done /dev/null route -qn add -net 127 127.0.0.1 -reject >/dev/null # Grab default route, if existent if [ -s /mnt/etc/hostname.local ]; then cmd="$(grep ^route /mnt/etc/hostname.local | grep default)" [[ -n $cmd ]] && eval "$cmd" fi # Display results... echo "Network interface configuration:" ifconfig -am # enable the resolver if resolv.conf is available route -n show if [ -f /etc/resolv.conf ]; then echo "\nResolver enabled." else echo "\nResolver not enabled." fi } # Install a user-selected subset of the files in $2 from the source # named in $1. Display an error message for failed installs so the # user will know to try again. install_files() { typeset _src=$1 _files=$2 _f _sets _get_sets # Initialize _sets to the list of sets found in _src, and initialize # _get_sets to the intersection of _sets and DEFAULTSETS. # # Sets will be installed in the order given in THESETS to ensure proper # installation. So, to minimize user confusion display the sets in the # order in which they will be installed. for _f in $THESETS; do isin $_f $_files || continue; _sets=$(addel $_f $_sets) isin $_f $DEFAULTSETS && _get_sets=$(addel $_f $_get_sets) done if [[ -z $_sets ]]; then # Show $_src, but delete any ftp password. cat <<__EOT No $OBSD sets were found at $(echo $_src | sed -e 's/\(^ftp:\/\/[^/]*\)\(:[^/]*\)\(@.*\)/\1\3/') Set names are: $THESETS __EOT return fi select_sets "$_sets" "$_get_sets" [[ -n $resp ]] || return _get_sets=$resp ask_yn "Ready to $MODE sets?" yes [[ $resp = n ]] && return for _f in $THESETS; do isin $_f $_get_sets || continue echo "Getting $_f ..." case $_f in *.ngz) ftp $_ftp_active -o - -V -m "$_src/$_f" | \ gzip -dcf | tar -M lncp -xphf - -C /mnt ;; *) ftp $_ftp_active -o "/mnt/$_f" -V -m "$_src/$_f" ;; esac if [ $? -ne 0 ]; then echo "'$_f' did not install correctly." else DEFAULTSETS=$(rmel $_f $DEFAULTSETS) fi done } # Encode $1 as specified for usercodes and passwords in RFC 1738 # section 3.1 and section 5. # # Escape everything between 0x20 and 0x7e to avoid both illegal url # characters and characters causing problems during script processing. # # *NOTE* # 1) quotes around $1 are required to preserve trailing or # embeddded blanks in usercodes and passwords. # 2) substitute '%' FIRST so it doesn't eliminate '%' chars we insert. encode_for_url() { print -nr -- "$1" | sed -e ' s.%.%25.g s.;.%3B.g s./.%2F.g s.?.%3F.g s.:.%3A.g s.@.%40.g s.&.%26.g s.=.%3D.g s.+.%2B.g s.\$.%24.g s.,.%2C.g s. .%09.g s. .%20.g s.<.%3C.g s.>.%3E.g s.#.%23.g s.".%22.g s.{.%7B.g s.}.%7D.g s.|.%7C.g s.\\.%5C.g s.\^.%5E.g s.\[.%5B.g s.].%5D.g s.`.%60.g s.'\''.%27.g s/!/%21/g s/(/%28/g s/)/%29/g s/\*/%2a/g s/-/%2d/g s/\./%2e/g s/_/%5f/g s/~/%7e/g ' } # Check for the presence of an error message in the output of the ftp commands # used to get the list of files in a directory. # # $1 = error message to look for # $2 = ftp command output ftp_error() { if [[ -n $(echo "$2" | grep "$1") ]]; then echo $1 return 0 fi return 1 } # Get several parameters from the user, and xfer # files from the server. # $1 = url type (ftp, http or https) # Note: _ftp_server_ip, _ftp_server_dir, _ftp_server_login, # and _ftp_active must be global. install_url() { typeset _url_type=$1 _file_list _url_base _oifs _prompt _passwd ask "HTTP/FTP proxy URL? (e.g. 'http://proxy:8080', or 'none')" \ "${ftp_proxy:-none}" unset ftp_proxy http_proxy [[ $resp = none ]] || export ftp_proxy=$resp http_proxy=$resp rm -f $SERVERLIST # ask_yn "Display the list of known $_url_type servers?" "${_get_server_list:-yes}" # _get_server_list=$resp _get_server_list=n # if [[ $_get_server_list = y ]]; then # # ftp.openbsd.org == 129.128.5.191 and will remain at # # that address for the forseeable future. # echo -n "Getting the list from 129.128.5.191 (ftp.openbsd.org)..." # ftp $_ftp_active -V -a -o - \ # ftp://129.128.5.191/$FTPDIR/ftplist 2>/tmp/ftplisterr \ # | sed -ne "/^${_url_type}:\/\//s///p" >$SERVERLIST # if [[ -s $SERVERLIST ]]; then # echo "done." # _prompt="Server? (IP address, hostname, list#, 'done' or '?')" # sed = $SERVERLIST | sed 'N;s/\n/ /' | less -XE # else # echo "FAILED." # cat /tmp/ftplisterr # fi # fi # Get server IP address or hostname : ${_prompt:="Server? (IP address, hostname or 'done')"} eval ': ${_'${_url_type}'_server_ip:=www.mirbsd.org}' while :; do eval resp=\$_${_url_type}_server_ip ask_until "$_prompt" "$resp" case $resp in done) return ;; "?") [[ -s $SERVERLIST ]] || continue sed = $SERVERLIST | sed 'N;s/\n/ /' | less -XE ;; +([0-9])) # A numeric hostname is ignored. A number is only used # as a line number in $SERVERLIST. [[ -s $SERVERLIST ]] || continue set -- $(sed -ne "${resp}p" $SERVERLIST) if (( $# < 1 )); then echo "There is no line $resp." continue fi echo "Using $*" eval _${_url_type}_server_ip=${1%%/*} eval _${_url_type}_server_dir=${1#*/}/$SETDIR # Repeat loop to get user to confirm server address. ;; *) eval _${_url_type}_server_ip=$resp break ;; esac done # Some older servers lie about their support for passive mode ftp, so # ask the user if it worth trying passive mode to the chosen server. # Irrelevant if using a proxy. if [[ $_url_type = ftp && -z $ftp_proxy ]]; then case $_ftp_active in -A) resp=no ;; *) resp=yes ;; esac unset _ftp_active ask_yn "Does the server support passive mode ftp?" $resp [[ $resp = n ]] && _ftp_active=-A fi # Get server directory eval resp=\$_${_url_type}_server_dir ask_until "Server directory?" "${resp:-$FTPDIR$SETDIR}" eval _${_url_type}_server_dir=$resp if [[ $_url_type = ftp ]]; then # Get login name, setting IFS to nothing so trailing or # embedded blanks are preserved! _oifs=$IFS IFS= ask_until "Login?" "${_ftp_server_login:=anonymous}" _ftp_server_login=$resp # Get password unless anonymous _passwd=root@$(hostname) if [[ $_ftp_server_login != anonymous ]]; then resp= while [[ -z $resp ]]; do askpass "Password? (will not echo)" done _passwd=$resp fi IFS=$_oifs fi # Build up the base url since it is so nasty... _url_base=$_url_type:// if [[ $_url_type = ftp && $_ftp_server_login != anonymous ]]; then _url_base=$_url_base$(encode_for_url "$_ftp_server_login"):$(encode_for_url "$_passwd")@ fi eval _url_base=$_url_base\$_${_url_type}_server_ip/\$_${_url_type}_server_dir # XXX Workaround for problems ftp'ing out from a v6 only host. ifconfig lo0 127.0.0.1 # Get list of files from the server. if [[ $_url_type = ftp && -z $ftp_proxy ]]; then _file_list=$(ftp_list_files "$_ftp_server_ip" "$_ftp_server_login" "$_passwd" "$_ftp_server_dir") ftp_error "Login failed." "$_file_list" && return ftp_error "No such file or directory." "$_file_list" && return else # Assumes index file is "index.txt" for http (or proxy) # We can't use index.html since the format is server-dependent _file_list=$(ftp -o - -V "$_url_base/index.txt" | sed 's/ //') fi install_files "$_url_base" "$_file_list" } install_mounted_fs() { typeset _dir while :; do ask_until "Pathname to the sets? (or 'done')" "$SETDIR" [[ $resp = done ]] && return # Accept a valid /mnt2 or /mnt relative path. [[ -d /mnt2/$resp ]] && { _dir=/mnt2/$resp ; break ; } [[ -d /mnt/$resp ]] && { _dir=/mnt/$resp ; break ; } # Accept a valid absolute path. [[ -d /$resp ]] && { _dir=/$resp ; break ; } echo "The directory '$resp' does not exist." done install_files "file://$_dir" "$(ls -l $_dir)" } install_cdrom() { typeset _drive _part=c _fstype _err=0 get_drive "CD-ROM" "$CDDEVS" || return _drive=$resp set -- $(disklabel $_drive 2>&1 | grep '^ c: ') || _err=1 case $_err:$4 in 1*|0:ISO9660) _fstype=cd9660 ;; 0:UDF) _fstype=udf ;; *) get_partition $_drive "cd9660" || return set -- $resp _part=$1 [[ -n $2 ]] && _fstype=$2 ;; esac mount -t $_fstype -o ro /dev/$_drive$_part /mnt2 || return install_mounted_fs } install_disk() { typeset _drive _dev _fstype _fsopts ask_yn "Is the disk partition already mounted?" if [[ $resp = n ]]; then get_drive "disk" "$DKDEVS" || return _drive=$resp get_partition $_drive "$MDFSTYPE" || return set -- $resp _dev=/dev/$_drive$1 [[ -n $2 ]] && _fstype="-t $2" [[ $_fstype = $MDFSTYPE ]] && _fsopts=$MDFSOPTS if [[ -z $(mount | grep "^$_dev") ]]; then mount $_fstype -o ro,$_fsopts $_dev /mnt2 || return fi fi install_mounted_fs } install_nfs() { typeset _tcp # Get the IP address of the server. ask_until "Server IP address or hostname?" "$NFS_ADDR" NFS_ADDR=$resp # Get the server path to mount. ask_until "Filesystem on server to mount?" "$NFS_PATH" NFS_PATH=$resp # Determine use of TCP ask_yn "Use TCP transport? (requires TCP-capable NFS server)" yes [[ $resp = y ]] && _tcp=-T # Mount the server mount_nfs $_tcp -o ro $NFS_ADDR:$NFS_PATH /mnt2 || return install_mounted_fs } install_tape() { typeset _z _bs # Get the name of the tape device. get_drive "tape drive" "$MTDEVS" || return export TAPE=/dev/nr$resp if [[ ! -c $TAPE ]]; then echo "$TAPE is not a character special file." return fi # Rewind the tape device. echo -n "Rewinding $TAPE (mt rewind)..." mt rewind || return echo "done." # Extract the desired files. while :; do ask_until "Skip how many files? (or 'done')" 0 [[ $resp = done ]] && return [[ $resp = +([0-9]) ]] || continue (( resp < 0 )) && continue if (( resp > 0 )); then echo -n "Skipping $resp file(s)..." mt fsf $resp || return echo "done." elif [[ -n $_bs ]]; then # Dance to start of next file. mt bsf ; mt fsf fi unset _z ask_yn "Is the file gzipped?" yes [[ $resp = y ]] && _z=z # Get the blocksize to use. If the file isn't gzipped then # default to the 20 x 512 = 10,240 byte tar default. [[ $_z = z ]] || _bs=10240 ask_until "Blocksize for this file?" "${_bs:-8k}" [[ $resp = done ]] && return _bs=$resp dd if=$TAPE bs=$_bs | tar -M lncp -${_z}xvphf - -C /mnt || \ return done } set_timezone() { typeset _zoneroot=/mnt/usr/share/zoneinfo/ _zonepath # If the timezone directory structure is not # available, return immediately. [[ ! -d $_zoneroot ]] && return if [[ -L /mnt/etc/localtime ]]; then TZ=$(ls -l /mnt/etc/localtime 2>/dev/null) TZ=${TZ#*${_zoneroot#/mnt}} fi : ${TZ:=GMT} while :; do _zonepath=$_zoneroot ask "What timezone are you in? ('?' for list)" "$TZ" if [[ $resp = ? ]]; then ls -F ${_zonepath} continue; fi _zonepath=${_zonepath}${resp} while [[ -d $_zonepath ]]; do ask "What sub-timezone of '${_zonepath#$_zoneroot}' are you in? ('?' for list)" case $resp in "") ;; ?) ls -F $_zonepath ;; *) _zonepath=$_zonepath/$resp ;; esac done if [[ -f $_zonepath ]]; then TZ=${_zonepath#$_zoneroot} echo -n "Setting local timezone to '$TZ'..." ln -sf /usr/share/zoneinfo/$TZ /mnt/etc/localtime echo "done." return fi echo -n "'${_zonepath#$_zoneroot}'" echo " is not a valid timezone on this system." done } # Check with the user that missing required sets were deliberately skipped. sane_install() { typeset _s _m for _s in $SANESETS; do isin $_s $DEFAULTSETS || continue ask_yn "'$_s' was not installed.\nAre you *SURE* your $MODE is complete without '$_s'?" [[ $resp = n ]] && _m="$_m $_s" done [[ -n $_m ]] && return 1 return 0 } # Ask the user for locations of sets, and then install whatever sets the # user selects from that location. Repeat as many times as the user # needs to get all desired sets. install_sets() { typeset _d=disk _locs="disk ftp http shttp" [[ -n $CDDEVS ]] && { _locs="cd $_locs" ; _d=cd ; } [[ -x /sbin/mount_nfs ]] && _locs="$_locs nfs" [[ -n $MTDEVS && -x /bin/mt ]] && _locs="$_locs tape" echo "\nLet's $MODE the sets!" while :; do umount -f /mnt2 >/dev/null 2>&1 [[ -z $DEFAULTSETS ]] && _d=done ask "Location of sets? ($_locs or 'done')" "$_d" case $resp in done) sane_install && return ;; c*|C*) isin "cd" $_locs && install_cdrom ;; d*|D*) install_disk ;; f*|F*) isin "ftp" $_locs && install_url ftp ;; h*|H*) isin "http" $_locs && install_url http ;; n*|N*) isin "nfs" $_locs && install_nfs ;; s*|S*) isin "http" $_locs && install_url https ;; t*|T*) isin "tape" $_locs && install_tape ;; esac done } # Create a skeletal but useful /etc/fstab from /tmp/fstab by stripping all # comment lines and dropping all filesystems which # # 1) can't be mounted (no mount_* command is found), # 2) have 'xx' in the option field (usually /altroot), # 3) have 'noauto' in the option field, # 4) are nfs (since name resolution may not be present), # 5) are mfs (breaks install usually). # # In addition, # # 2) mount non-ffs filesystems read only, # 3) prepend '/mnt' to all mount points, # 4) delete any trailing '/' from the mount point (e.g. root), # 5) leave out fs_freq and fs_passno fields. # # If no /etc/fstab is created, do not proceed with install/upgrade. munge_fstab() { typeset _dev _mp _fstype _opt _rest while read _dev _mp _fstype _opt _rest; do # Drop irrelevant lines and filesystems. [[ $_dev = \#* || \ $_fstype = nfs || \ $_fstype = mfs || \ ! -f /sbin/mount_$_fstype || \ $_opt = *noauto* || \ $_opt = *xx* ]] && continue # Mount non-ffs filesystems read only. [[ $_fstype = ffs ]] || _opt=$(echo $_opt | sed -e 's/rw/ro/') # Write fs entry in fstab. # 1) prepend '/mnt' to the mount point. # 2) remove a trailing '/' from the mount point (e.g. root). # 3) leave out fs_freq and fs_passno fields (i.e. $_rest). echo $_dev /mnt${_mp%/} $_fstype $_opt done /etc/fstab # If no /etc/fstab was created, we have nowhere to $MODE to. if [ ! -s /etc/fstab ]; then echo "Unable to create valid /etc/fstab." exit fi } # Must mount filesystems manually, one at a time, so we can make # sure the mount points exist. mount_fs() { typeset _async=$1 _dev _mp _fstype _opt _rest while read _dev _mp _fstype _opt _rest; do # If not the root filesystem, make sure the mount # point is present. [ "$_mp" = "/mnt" ] || mkdir -p $_mp # Mount the filesystem. If the mount fails, exit. mount -v -t $_fstype $_async -o $_opt $_dev $_mp && continue # If it failed, try without async (important for raid) first mount -v -t $_fstype -o $_opt $_dev $_mp && continue # In addition to the error message displayed by mount ... cat <<__EOT FATAL ERROR: Cannot mount filesystems. Double-check your configuration and restart the $MODE. __EOT exit done /dev/arandom } # Preen all filesystems in /etc/fstab that have a /sbin/fsck_XXX, # showing individual results, but skipping $ROOTDEV. This was already # fsck'ed successfully. # # Exit if any fsck's fail (but do them all before exiting!). check_fs() { typeset _dev _mp _fstype _rest _fail echo "Checking non-root filesystems..." while read _dev _mp _fstype _rest; do [ "$_dev" != /dev/"$ROOTDEV" ] || continue [ -f "/sbin/fsck_$_fstype" ] || continue # Make sure device exists before fsck'ing it. _rest=${_dev#/dev/} makedev ${_rest%[a-p]} || continue echo -n "fsck -p ${_dev}..." if ! fsck -fp ${_dev} >/dev/null 2>&1; then echo "FAILED. You must fsck $_dev manually." _fail=y else echo "OK." fi done /tmp/resolv.conf echo "lookup file bind" >>/tmp/resolv.conf for _ns in $resp; do echo "nameserver $_ns" >>/tmp/resolv.conf done ask_yn "Use the nameserver now?" yes [[ $resp = y ]] && cp /tmp/resolv.conf /tmp/resolv.conf.shadow fi edit_tmp_file hosts manual_net_cfg } questions() { [[ -e /mnt/etc/rc.conf.local ]] && mv -f /mnt/etc/rc.conf.local \ /mnt/etc/rc.conf.local~ ask_yn "Start sshd(8) by default?" yes if [[ $resp = n ]]; then echo "sshd_flags=NO # disabled during install" \ >>/mnt/etc/rc.conf.local~ fi ask_yn "Start ntpd(8) by default?" yes if [[ $resp = y ]]; then echo "ntpd_flags= # enabled during install" \ >>/mnt/etc/rc.conf.local~ echo "rdate_flags='-nv ntp.mirbsd.org'" >>/mnt/etc/rc.conf.local~ fi if [[ -e /mnt/etc/rc.conf.local~ ]]; then (echo '# $MirSecuCron$'; echo; cat /mnt/etc/rc.conf.local~) \ >/mnt/etc/rc.conf.local rm -f /mnt/etc/rc.conf.local~ fi if [[ -n $MDXAPERTURE ]]; then echo 'This setting affects the machdep.allowaperture sysctl.' echo 'If you respond negatively, you must enable it later in' echo '/etc/sysctl.conf in order to be able to run XFree86(R).' if [[ -e /mnt/usr/X11R6/bin/X ]]; then resp=yes else resp=no fi ask_yn "Do you expect to run the X Window System?" $resp if [[ $resp = y ]]; then sed -e "/^#\(machdep\.allowaperture=${MDXAPERTURE}\)/s//\1 /" \ /mnt/etc/sysctl.conf >/tmp/sysctl.conf cp /tmp/sysctl.conf /mnt/etc/sysctl.conf fi fi echo 'The size for the RSA host key can now be selected here. Larger' echo 'key sizes usually mean more security, but always imply much' echo 'longer key exchange times (e.g. mail delivery, ssh login), so' echo 'they are not recommended for old boxen (say, a SPARCstation)' echo 'or if you have to communicate with them very often; choose a' echo 'lower size (e.g. 2048) than the default of 4096 then.' ask_which "size" "should the RSA host key have" \ "2048 3072 4096 6144 8192" 4096 [[ $resp = done ]] || print "/4096/s//$resp/\nwq" | ed -s /mnt/etc/rc [[ -z $SERIALDEV ]] && return ask_yn "Change the default console to $SERIALDEV?" [[ $resp = n ]] && return ask_which "speed" "should $SERIALDEV use" "9600 19200 38400 57600 115200" [[ $resp = done ]] && return echo '# $MirSecuCron$' >/mnt/boot.cfg echo "set tty $SERIALDEV\nstty $SERIALDEV $resp" >>/mnt/boot.cfg } finish_up() { typeset _dev _mp _fstype _rest # Mount all known swap partitions. This gives systems with little # memory a better chance at running 'MAKEDEV all'. if [[ -x /mnt/sbin/swapctl ]]; then /mnt/sbin/swapctl -a /dev/$SWAPDEV >/dev/null 2>&1 # Can't do chmod && swapctl -A because devices are not yet # created on install'ed systems. On upgrade'ed system there # is a small chance the device does not exist on the ramdisk # and will thus not get mounted. while read _dev _mp _fstype _rest; do [[ $_fstype = swap ]] && \ /mnt/sbin/swapctl -a $_dev >/dev/null 2>&1 done /tmp/sysctl.conf cp /tmp/sysctl.conf /mnt/etc/sysctl.conf fi echo -n "Making all device nodes..." cd /mnt/dev mksh MAKEDEV all # Make sure any devices we found during probe are created in the # installed system. for _dev in $DKDEVS $CDDEVS $MTDEVS; do mksh MAKEDEV $_dev done echo "done." cd / if [[ -e $ROOTDISK ]]; then _dev=$ROOTDISK else _dev=/dev/r${ROOTDISK}c fi # use extracted mdec if it exists (may be newer) if [ -e /mnt/usr/mdec/boot ]; then _prefix=/mnt/usr/mdec elif [ -e /usr/mdec/boot ]; then _prefix=/usr/mdec else _prefix= fi if [[ ! -e $_dev ]]; then print Cannot install bootblocks to "'$ROOTDISK'". print You must run installboot manually. elif [[ -z $_prefix ]]; then print No boot block prototypes found. print You must run installboot manually. else print Installing boot block... cat ${_prefix}/boot >/mnt/boot chmod 0 /mnt/boot sync; sync; sync ${_prefix}/installboot -v /mnt/boot ${_prefix}/bootxx $_dev print done. fi [ -x /mnt/$MODE.fixes ] && /mnt/usr/sbin/chroot /mnt /$MODE.fixes [ -x /mnt/$MODE.site ] && /mnt/usr/sbin/chroot /mnt /$MODE.site # Pat on the back. cat <<__EOT CONGRATULATIONS! Your MirBSD $MODE has been successfully completed! To boot the new system, enter halt at the command prompt. Once the system has halted, reset the machine and boot from the disk. Hello there! We from the MirOS project would like to hear from you! If you installed or updated your existing MirOS installation, which architecture, maybe your country, a dmesg and a few words about how you like MirOS. If you don't mind being counted to help us estimate our userbase, mail to - thanks in advance! __EOT md_congrats } # ####################################################################### # # Initial actions common to both installs and upgrades. # # Some may require machine dependent routines, which may # call functions defined above, so it's safest to put this # code here rather than at the top of the file. # # ####################################################################### ulimit -c 0 ROOTDISK= ROOTDEV= VERSION=10 # FTPDIR: prefix for SETDIR for ftp/http/https installs FTPDIR="MirOS/" #SETDIR="v${VERSION}/$ARCH" #OBSD="MirOS BSD #$VERSION/$ARCH" SETDIR="current/$ARCH" OBSD="MirOS BSD #$VERSION-current/$ARCH" SERVERLIST=/tmp/serverlist # Do not limit ourselves during installs or upgrades. for _opt in d f l m n p s; do ulimit -$_opt unlimited done # Scan /var/run/dmesg.boot for interesting devices. DKDEVS=$(scan_dmesg "${MDDKDEVS:-/^r*a*[swi]d[0-9][0-9]* /s/ .*//p}") CDDEVS=$(scan_dmesg "${MDCDDEVS:-/^cd[0-9][0-9]* /s/ .*//p}") MTDEVS=$(scan_dmesg "${MDMTDEVS:-/^[cmsw]t[0-9][0-9]* /s/ .*//p}") SERIALDEV=$(get_serialdev) # Selected sets will be installed in the order they are listed in $THESETS. # Ensure that siteXX.ngz is the *last* set listed so its contents overwrite # the contents of the other sets, not the other way around. Similarly fixes # must be second-to-last. THESETS="bsd bsd.rd $MDSETS" DEFAULTSETS="bsd" for _set in base etc gnu dev ada xbase xetc xfont xserv unfree pkgutl ports \ source xfree pkgsrc psbsk fixes site; do [[ $MODE = upgrade && $_set = @(?(x)etc|ports|source|xfree|pkgsrc|psbsk) ]] && continue THESETS="$THESETS ${_set}${VERSION}.ngz" isin $_set base etc gnu dev fixes && \ DEFAULTSETS="$DEFAULTSETS ${_set}${VERSION}.ngz" done # Since etc${VERSION}.ngz is not in DEFAULTSETS for upgrades, it can always be # in SANESETS. SANESETS="bsd base${VERSION}.ngz etc${VERSION}.ngz" # decide upon an editor : ${EDITOR:=ed} [[ -x /usr/bin/vi ]] && EDITOR=vi export EDITOR # umount all filesystems, just in case we are re-running install or upgrade. [[ -f /etc/fstab ]] && umount -avt nomfs 1>/dev/null 2>&1 umount -v /mnt 1>/dev/null 2>&1 # Introduce ourselves. welcome # Get ROOTDISK, ROOTDEV and SWAPDEV. if [[ $MODE = install && ! -f /etc/fstab ]]; then cat <<__EOT You will now initialise the disk(s) that MirBSD will use. To enable all available security features you should configure the disk(s) to allow the creation of separate filesystems for /, /tmp, /var, /usr, and /home. __EOT fi set -- $DKDEVS (( $# > 1 )) && _defdsk=done ask_which "disk" "is the root disk" "$DKDEVS" "$_defdsk" [[ $resp = done ]] && exit makedev $resp || exit ROOTDISK=$resp ROOTDEV=${ROOTDISK}a SWAPDEV=${ROOTDISK}b