#! /bin/bash # this provides environment and functions needed by install scripts. # must be sourced by the scripts. if [ -e /etc/default/vyatta ] ; then . /etc/default/vyatta fi : ${vyatta_prefix:=/opt/vyatta} : ${vyatta_exec_prefix:=$vyatta_prefix} : ${vyatta_bindir:=${vyatta_exec_prefix}/bin} : ${vyatta_sysconfdir:=${vyatta_prefix}/etc} # trap signals so we can kill runaway progress indicators trap 'progress_indicator stop; exit 1' 1 trap 'progress_indicator stop; exit 1' 2 # mount point for the install root. # for union install, this is a r/w union mount. # for non-union install, this is the root partition mount. INST_ROOT=/mnt/inst_root # mount point for the writable root, i.e., the root partition. # this is only used for union install. WRITE_ROOT=/mnt/wroot # mount point for the readonly squashfs mount. # this is only used for union install. READ_ROOT=/mnt/squashfs # mount point for the ISO image. # this is only used when installing with an ISO image file # (instead of from a live CD boot). CD_ROOT=/mnt/cdrom # mount point for the squashfs image in the ISO image. # this is only used when installing with an ISO image file # (instead of from a live CD boot). CD_SQUASH_ROOT=/mnt/cdsquash # the vyatta config dir VYATTA_CFG_DIR=${vyatta_sysconfdir}/config # the floppy config dir FD_CFG_DIR=/media/floppy/config # PROGRESS_PID can be exported by top-level script progress_indicator () { local spid=$PROGRESS_PID if [ -z "$spid" ]; then spid=$$ fi case "$1" in start) $vyatta_bindir/progress-indicator $spid & ;; *) if ! rm /tmp/pi.$spid 2>/dev/null; then sleep 1 rm /tmp/pi.$spid 2>/dev/null fi sleep 1 echo -n -e "\b" ;; esac } # echo to log. uses INSTALL_LOG if set. lecho () { local log=$INSTALL_LOG if [ -z "$log" ]; then log=/tmp/install-$$.log fi echo -e "$*" >>$log } # echo to both. becho () { lecho "$*" echo -e "$*" } tolower () { echo "$*" | tr '[:upper:]' '[:lower:]' } # Validates a user response. Returns the response if valid. # Returns the default is the user just hits enter. # Returns nothing if not valid. Default parameter is $1. # Options are in $2. If options are defined return must be a member # of the enum. get_response () { local ldefault=$(tolower "$1") local loptions=$(tolower "$2") # get the response from the user read myresponse myresponse=$(tolower "$myresponse") # Check to see if the user accepts the default if [ -z "$myresponse" ]; then echo -n $ldefault elif [ -n "$loptions" ]; then # make sure response is a valid option for token in $loptions do if [ "$token" == "$myresponse" ]; then echo -n "$myresponse" return 0 fi done return 1 else echo -n "$myresponse" fi return 0 } # turn off any mounted swap partitions turnoffswap () { if [ -f "/proc/swaps" ]; then myresponse=$(cat /proc/swaps) if [ -n "$myresponse" ]; then lecho "turning off swaps..." swapoff -a fi fi } # Return the size of the drive in MB get_drive_size () { ldrive=$1 # Make sure you can print disk info using parted parted --script /dev/$ldrive p >/dev/null 2>&1 # If unable to read disk, it's likely it needs a disklabel if [ "$?" != "0" ]; then lecho "Creating a new disklabel on $ldrive" lecho "parted /dev/$ldrive mklabel msdos" output=$(parted -s /dev/$ldrive mklabel msdos) # Get the drive size from parted lsize=$(parted -s /dev/$ldrive p | grep "^Disk" | awk '{ print $3 }') if [ $(echo $lsize | grep error) ]; then echo "Unable to read disk label. Exiting." exit 1 fi fi # Get the drive size from parted lsize=$(parted -s /dev/$ldrive p | grep "^Disk" | awk '{ print $3 }') # Get the reported units (mB, GB, kB) lmodifier=$(echo $lsize | sed 's/[0-9\.]//g') # remove the modifier lsize=$(echo $lsize | sed 's/[a-z,A-Z]//g') # Remove any fractions lsize=$(echo $lsize | cut -f1 -d'.') # Translate our size into mB if not there already if [ $lmodifier = "GB" ]; then lsize=$(($lsize * 1000)) elif [ $lmodifier = "kB" ]; then lsize=$(($lsize / 1000)) fi echo $lsize } # Probe hardrives not shown in /proc/partitions by default probe_drives () { # Find drives that may not be in /proc/partitions since not mounted drive=$(ls /sys/block | grep '[hsv]d.') # now exclude all drives that are read-only for drive in $drive; do if [ $(cat /sys/block/$drive/ro) -ne 0 ]; then output=$(mount | grep $drive) if [ -z "$output" ]; then output=$(parted -s /dev/$drive p) fi fi done } # Display text $1 before choice. # Sets the variable named by $2. # Note that select_drive should be wrapped # in the verification loop, not the included get_response. select_drive () { local msg=$1 local outvar=$2 local drv='' # list the drives in /proc/partitions. Remove partitions and empty lines. # the first grep pattern looks for devices named c0d0, hda, and sda. drives=$(cat /proc/partitions | \ awk '{ if ($4!="name") { print $4 } }' | \ egrep "c[0-9]d[0-9]$|[hsv]d[a-z]$" | \ egrep -v "^$") # take the first drive as the default drv=$(echo $drives | /usr/bin/awk '{ print $1 }') # Add the drive sizes to the display to help the user decide display='' for drive in $drives; do size=$(get_drive_size $drive) display="$display $drive\t$size"MB"\n" done while true; do # Display the drives and ask the user which one to install to echo -e "$display" echo echo -n "$1 [$drv]:" response=$(get_response "$drv" "$drives") && break done eval "$outvar=$response" echo } # $1: user name # $2: encrypted password # $3: config file set_encrypted_password () { sed -i -e \ "/ user $1 {/,/}/s/encrypted-password.*\$/encrypted-password \"$2\"/" $3 } # interactively prompt user to change password for the specified account in # the specified config file # $1: account name # $2: config file change_password() { local user=$1 local config=$2 local pwd1="1" local pwd2="2" until [ "$pwd1" == "$pwd2" ]; do read -p "Enter $user password:" -r -s pwd1 <>/dev/tty 2>&0 echo read -p "Retype $user password:" -r -s pwd2 <>/dev/tty 2>&0 echo if [ "$pwd1" != "$pwd2" ]; then echo "Passwords do not match" fi done # escape any slashes in resulting password local epwd=$(mkpasswd -H md5 "$pwd1" | sed 's:/:\\/:g') set_encrypted_password "$user" "$epwd" "$config" } # returns true if it's a disk-based boot is_disk_based_boot() { islive=`grep boot=live /proc/cmdline` if [ -z "$islive" ]; then # Return value 0 is "true" is shell return 0 else return 1 fi } # returns true if it's a live cd boot is_live_cd_boot () { if grep -q ' /live/image [^ ]\+ ro' /proc/mounts; then return 0 else return 1 fi } # returns true if it's a union-install boot is_union_install () { if is_live_cd_boot; then return 1 fi if grep -q ' /live/image [^ ]\+ rw' /proc/mounts \ && grep -q 'unionfs / unionfs ' /proc/mounts; then return 0 else return 1 fi } # outputs the version string of the current running version. get_cur_version () { ver=`dpkg-query --showformat='${Version}' --show vyatta-version` if [ -z "$ver" ]; then echo "UNKNOWN" else echo $ver fi } # outputs the version string of the new version, i.e., the version that is # being installed. this can be from live CD boot or from a ISO image file. get_new_version () { ver_path=/var/lib/dpkg/status ver_file=${CD_SQUASH_ROOT}${ver_path} if [ -f "$ver_file" ]; then # CD_SQUASH_ROOT is set up => we are installing with a specified ISO # image file. use the version string from there. dpkg -l --root=${CD_SQUASH_ROOT} | \ grep "^.. vyatta-version " | awk '{print $3}' return fi ver_file=${ver_path} if is_live_cd_boot && [ -f "$ver_file" ]; then # we are installing from a live CD boot ver=`dpkg-query --showformat='${Version}' --show vyatta-version` echo $ver return fi # couldn't find it } # try to mount. log any errors and return the appropriate status. # $1: arguments for mount try_mount () { args="$*" output=$(eval "mount $args 2>&1") status=$? if [ $status == 0 ]; then return 0 fi # error cat <