#!/bin/sh
#
# $Id: script-header,v 1.27.2.2.2.1 2003/06/12 21:45:38 sjg Exp $
#
# Copyright (c) 1999-2003, Juniper Networks, Inc.
# All rights reserved.
#
# Package requirement review and installation script (base form)
#
# This script is run after the tar file has been unpacked into the /var
# sandbox area but before anything has actually been moved to the final
# location upon installation, and also once again upon deinstallation.
#
# When it is called for installation via REQUIRE, it's called with
# the second argument set to "INSTALL", upon deinstallation "DEINSTALL".
# When it's called for installation via INSTALL, it's called with
# "PRE-INSTALL" and "POST-INSTALL". We leave it to the derived script
# to deal with these conditions; we just record them in $instance.
#
# The model is that each package's REQUIRE script defines a set of
# variables that represent the facilities (and internal version
# number of those facilities) offered or required by that package.
# The functions in this file get those variables and compare them
# to see if the services required match those offered. Other scripts
# allow the user to check whether a set of packages will work together
# or if a reboot is (or will be) required after upgrade.
# 
# $PKG_* variables are set by the "package" script
#

#
# If we're only after variable-setup, we don't want _anything_
# out of this file. The cloing 'fi' for the following 'if' is
# the last thing in this file. Thing of this as '#ifndef foo/#define foo'
# lines from a C header file....
#
if [ -z "$PKG_SETUP_VARIABLES_ONLY" ]; then
# The closing 'fi' is at the bottom of the file.

pkg_LCK=/tmp/.pkg.LCK
pkg_db_dir=/etc/db/pkg
pkg_tag=
fail=0

# UI variable settings
mgd=/usr/sbin/mgd
mgd_last=$mgd.last
config_database=/var/db/juniper.db
old_config_database=/config/juniper.db
# handle compressed configs
for config_file in /config/juniper.conf.gz /config/juniper.conf
do
    [ -f $config_file ] && break
done
config_changes=/var/db/config/juniper.conf.pre-install

jkernel_require=/var/run/jkernel.require

# from debug.sh

DEBUGGING=
DEBUG_DO=:
DEBUG_SKIP=
export DEBUGGING DEBUG_DO DEBUG_SKIP

_debugOn() {
	DEBUG_OFF=
	DEBUG_DO=
	DEBUG_SKIP=:
	set -x
	DEBUG_ON=$1
}

_debugOff() {
	DEBUG_OFF=$1
	set +x
	DEBUG_ON=$2
	DEBUG_DO=:
	DEBUG_SKIP=
}

# Turn on debugging if appropriate
DebugOn() {
	local e

	case "${DEBUG_SH:-$DEBUG}" in
	"")	return 1;;
	esac
	# if debuggin is off because of a !e
	# don't add 'all' to the On list.
	case "$DEBUG_OFF" in
	"")	e=all;;
	*)	e=;;
	esac
	for e in ${*:-$Myname} $e
	do
		case ",${DEBUG_SH:-$DEBUG}," in
		*,!$e,*|*,!$Myname:$e,*)
			# only turn it off if it was on
			$DEBUG_DO _debugOff $e $DEBUG_ON
			return 0
			;;
		*,$e,*|*,$Myname:$e,*)
			# only turn it on if it was off
			$DEBUG_SKIP _debugOn $e
			return 0
			;;
		esac
	done
	return 1
}

# Only turn debugging off if one of our args was the reason it
# was turned on.
DebugOff() {
	local e

	for e in $*
	do
		case "$DEBUG_OFF" in
		"")	break;;
		$e)	_debugOn $DEBUG_ON; return 0;;
		esac
	done
	for e in $*
	do
		case "$DEBUG_ON" in
		"")	break;;
		$e)	_debugOff; return 0;;
		esac
	done
	return 0		# always happy
}

# return the first of $* that exists
# we generally use this to deal with expanding wildcards.
Exists() {
    case "$1" in
    -?) _t=$1; shift;;
    *) _t=-s;;
    esac
    for f in $*
    do 
	[ $_t $f ] || continue
	echo $f
	break
    done
}

# make it easier to add per-package tweaks without having to
# re-introduce cut/paste hell.
run_hooks() {
    eval __h="\$$1"
    for e in $__h
    do
        $e
    done
}

#
# trace <args>
#
# make a trace message
#
trace() {
    if [ ! -z "$PKG_TRACE_ENABLED" ]; then
	echo "trace:" "$*"
    fi
}

jkernel_require_is_not_old() {
    local uname cur
    uname=`uname -v | awk '{print $2}'`
    cur=`awk -F= '/^current_release/ { print $2 }' < $jkernel_require`
    [ "$uname" = "$cur" ]
}

#
# dot_jkernel_require
#
# At boot time, the currently installed jkernel's +REQUIRE
# script's variables are tucked into /var/run/jkernel.require
# so we can know information about the running kernel.
dot_jkernel_require() {
    if [ -r $jkernel_require ]; then
	if jkernel_require_is_not_old ; then
	    trace Sourcing jkernel.require ...
	    . $jkernel_require
	fi
    fi
}

# dot_run_require
#
# Generic form of dot_jkernel_require
# Currently used for jbase.
dot_run_require() {
    local run_require

    run_require=/var/run/$1.require
    if [ -r $run_require ]; then
        trace Sourcing $1.require ...
	. $run_require
    fi
}

# make_symlink <src> <target>
#
# if <target> does not already point at <src>
# make the link.
# The goal is to minimize writes to the flash

make_symlink() {
    DebugOn make_symlink
    local src target target_dir
    src=$1 
    target=$2

    if [ -h $DESTDIR$target ]; then
        case `/bin/ls -l $DESTDIR$target` in
	*"> $src")
            trace "make_symlink: ok: $DESTDIR$target -> $src"
            return;;
	esac
    fi
    trace "make_symlink: making: $DESTDIR$target -> $src"
    target_dir=`dirname $DESTDIR$target`
    [ -d $target_dir ] || mkdir -p $target_dir
    /bin/ln -sf $src $DESTDIR$target
    DebugOff make_symlink
}

# make_symlinks <package-name>
#
# If the file symlinks exists, we compare it to
# the one for the previous version of <package-name>
# and implement any changes.

make_symlinks() {
    DebugOn make_symlinks
    local symlinks old_symlinks

    symlinks=${1:-./$package.symlinks}
    old_symlinks=${2:-$pkgdir/$package.symlinks}
    
    if [ -s $symlinks ]; then
        if [ -s $old_symlinks ]; then
            # get rid of links which may no longer be correct
            diff $old_symlinks $symlinks | while read op src target flags
	    do
                case "$op" in
		"<") # delete - but only if it still points at src
                     # and isn't no_unlink
                     case "$flags" in
		     *no_unlink*) continue;;
		     esac
                     if [ -h $DESTDIR$target ]; then
                         case `/bin/ls -l $DESTDIR$target` in
			 *"> $src")
                             trace "make_symlinks: removing: $DESTDIR$target -> $src"
                             /bin/rm -f $DESTDIR$target
                             ;;
			 esac
		     fi
                     ;;
		esac
            done
	fi
        # make sure that the ones that should be there, are.
        while read src target flags
	do
	    make_symlink $src $target
        done < $symlinks
    fi
    DebugOff make_symlinks
}

# rm_symlinks <package-name>
#
# If the file $pkgdir/$package.symlinks exists
# we remove the links that are not marked no_unlink
# This should only be called for non-core packages and when
# $PKG_FORCE is set.
#
rm_symlinks() {
    DebugOn rm_symlinks
    local old_symlinks

    old_symlinks=${1:-$pkgdir/$package.symlinks}

    if [ -s $old_symlinks ]; then
        while read src target flags
	do
	    case "$flags" in
	    *no_unlink*) continue;;
	    esac
	    /bin/rm -f $DESTDIR$target
	done < $old_symlinks
    fi
    DebugOff rm_symlinks
}

# compatability routines for transition...
symlink_package() {
    make_symlinks
}

rm_symlink_package() {
    case "$package" in
    jbase|jroute|jkernel|jpfe*|jdocs)
        [ "$PKG_FORCE" ] || return
        ;;
    esac
    rm_symlinks
}

# code that shouldn't be replicated in each +[DE]INSTALL
package_pre_install() {
    DebugOn package_pre_install
    run_hooks ${package}_pre_install_hooks
    replace_package_mount

    [ -d /usr/share/help/syslog-modules ] ||
        (umask 022; /bin/mkdir -p /usr/share/help/syslog-modules)
    DebugOff package_pre_install
}

package_post_install() {
    DebugOn package_post_install
    run_hooks ${package}_post_install_hooks
    if [ ! -s $pkgdir/$pkgfile ]; then
        # it was marked @ignore_inst
        trace installing $pkgdir/$pkgfile
        cp -p .$base_pkgdir/$pkgfile $pkgdir
	/usr/bin/chflags schg $pkgdir/$pkgfile 
    fi
    make_symlinks
    if [ -s ./$package.symlinks ]; then
        # will need these later
        trace installing $pkgdir/$package.symlinks
        cp -p ./$package.symlinks $pkgdir/$package.symlinks
    fi
    if [ -z "$PKG_BOOTSTRAP" ] ; then
        # even if we plan to reboot, we need to mount the packages
        # in case the user delays rebooting and wants to install
        # something else.
        case `mount | grep "$pkgfile "` in
	"") trace mounting $pkgfile
	    /bin/sh $base_mountpkg
	    ;;
	esac
    fi
    [ -d /var/db/help ] ||
        (umask 022; /bin/mkdir -p /var/db/help )
    [ -s /usr/share/help/syslog-modules/$package.help.tgz ] &&
        /bin/rm -f /var/db/help/syslog.help.tgz
    DebugOff package_post_install
}

# common deinstall functionality
package_deinstall() {
    DebugOn package_deinstall
    run_hooks ${package}_deinstall_hooks
    case "$package" in
    jbase|jroute|jkernel|jpfe*|jdocs)
        [ "$PKG_FORCE" ] || { DebugOff package_deinstall; return; }
        ;;
    esac
    /bin/rm -df $base_mountdir
    /bin/rm -f $mountpkg
    /bin/rm -f $base_mountpkg
    rm_symlink_package
    DebugOff package_deinstall
}

package_post_deinstall() {
    DebugOn package_post_deinstall
    run_hooks ${package}_post_deinstall_hooks
    case "$package" in
    jbase|jroute|jkernel|jpfe*|jdocs)
        [ "$PKG_FORCE" ] || { DebugOff package_post_deinstall; return; }
        ;;
    esac
    case "$package" in
    jkernel)
        /bin/rm -f $base_umountpkg
        ;;
    *)
        [ -s $umountpkg ] && /bin/sh ${umountpkg} 2>/dev/null
        /bin/rm -f $base_umountpkg
        /bin/df | /usr/bin/grep -q "$mountdir"
        if [ $? = 1 ] ; then
    	    /bin/rm -f $umountpkg
	    /bin/rm -df $mountdir
        fi
        ;;
    esac
    # will still be there if marked @ignore_inst
    /usr/bin/chflags noschg $pkgdir/$pkgfile >/dev/null 2>&1
    /bin/rm -f $pkgdir/$pkgfile $pkgdir/$package $pkgdir/$package.symlinks
    DebugOff package_post_deinstall
}


# cleanup_package <package> <ignore>
#
# this routine cleans up the previously mounted versions of
# <package>, being careful to ignore <ignore> (usually pkgfile)
# incase we are installing the same version of the package.
# 
cleanup_package() {
    DebugOn cleanup_package
    local package ignore needclean mounted pkg pkgpath

    package=$1
    ignore=${2:-$pkgfile}

    trace cleanup_package $package $ignore

    case $package in
    *)    pkgmatch="$package-";;
    esac
    needclean=/tmp/.cln$$
    mounted=/tmp/.cln$$.m
    > $needclean
    > $mounted
    #
    # note that this will never match jbase - that only gets
    # unmounted at reboot time
    #
    mount | sed -n "/mnt\/$pkgmatch/s,mnt/,mnt ,p" |
    while read vndev j1 j2 mounted_package j3
    do
	echo ${mounted_package##*/} >> $mounted
        case "$mounted_package" in
	$ignore) trace skipping $ignore
            continue
            ;;
	esac
        trace cleaning up $mounted_package
        # try to unmount it
        if umount $pkgdir_mnt/$mounted_package 2>/dev/null; then
            vnconfig -u -v $vndev >/dev/null 2>&1
	    rm -f $base_pkgdir/umount.$mounted_package
	else
	    # communicating to the parent of a redirected
	    # loop can be a pain...
	    echo $package > $needclean
	fi
        if [ -s $base_pkgdir/mount.$mounted_package ]; then
            # see if it can tell us where the pkgfile is
            eval `grep pkgpath= $base_pkgdir/mount.$mounted_package; :`
        fi
        pkgpath=${pkgpath:-$pkgdir/$mounted_package}
        rm -f $base_pkgdir/mount.$mounted_package
        rm -df $pkgdir_mnt/$mounted_package 2>/dev/null
        chflags noschg $pkgpath >/dev/null 2>&1
        rm -f $pkgpath
    done
    if [ -s $needclean ]; then
	clean_pkg_list="$clean_pkg_list $package"
    fi
    /bin/rm -f $needclean
    (cd $pkgdir
    for old_package in ${pkgmatch}*
    do
        case "$old_package" in
	$ignore) trace skipping $ignore
            continue
            ;;
	*\*) break;;		# there are none?
	esac
        trace cleaning up $old_package
        rm -df $pkgdir_mnt/$old_package 2>/dev/null
	chflags noschg $old_package >/dev/null 2>&1
        rm -f $base_pkgdir/*mount.$old_package $old_package
    done
    # real dregs...
    cd $base_pkgdir
    for old_package in *mount.${pkgmatch}*
    do
	case "$old_package" in
	*.$ignore) trace skipping $ignore
            continue
	    ;;
	*\*) break;;		# there are none?
	esac
	trace cleaning up $old_package
	rm -f $old_package
    done
    cd $pkgdir_mnt
    mounted=`cat $mounted; rm -f $mounted`
    for old_mnt in ${pkgmatch}*
    do
	case "$old_mnt" in
	$ignore) trace skipping $ignore
            continue
            ;;
	*\*) break;;		# there are none?
	esac
	case " $mounted " in
	*" $old_mnt "*) continue;;
	esac
	trace cleaning up old mountdir $old_mnt
	rmdir $old_mnt 2>/dev/null || trace $old_mnt still busy
    done
    )
    trace cleanup_package finished.
    DebugOff cleanup_package
}

# Don't assume that pkg_delete did anything but
# remove the record of the package being installed.
# 
replace_package_mount() {
    DebugOn replace_package_mount
    trace replacing mount for $package $pkgfile

    cleanup_package $package $pkgfile

    # we don't get called for jbase, but just in case...
    if [ "$package" != jbase ]; then
        create_mount_package $pkgdir/$pkgfile $mountdir > $mountpkg
        create_umount_package $mountdir > $umountpkg
        make_package_links
	if [ -z "$PKG_BOOTSTRAP" -a "$clean_pkg_list" -a -s $pkgdir/cleanup-pkgs ]; then
	    if ! need_to_reboot; then
		trace Spawning cleanup-pkgs
		/bin/sh $pkgdir/cleanup-pkgs >> /var/log/cleanup-pkgs 2>&1 < /dev/null &
	    fi
	fi
    fi
    DebugOff replace_package_mount
}

#
# initialize <package-name> <pass-name>
#
# Initialize the environment
#
initialize() {
    DebugOn initialize
    if [ ! -z "$PKG_TRACE_SHELL" ]; then
	set -x
	set # Show current variable settings
    fi

    trace Initialing $0 package $1 for operation $2 in `pwd`

    # Package name
    package=$1

    # instance will be INSTALL/DEINSTALL/PRE-INSTALL/POST-INSTALL
    instance=$2

    # Fix the path to a known good value
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:${PATH}
    export PATH

    # We have (probably) just extracted the entire package into
    # the current directory ($instmp)
    instmp=`pwd`

    if [ -z $PKG_BOOTSTRAP ] ; then
        dot_jkernel_require
    fi
    #
    # The various mount/umount scripts
    # Some wrinkles due to the fact that we have jpfe-*
    # which we want registered as jpfe.
    # Thus we no longer assume that pkgfile=$package-5.7R2.4.
    # base_* are the canonical locations - known to /etc/rc et al
    # the distinction between base_pkgdir and pkgdir is that for
    # packages like jdiag and jtools pkgdir may be set to
    # /var/packages so that the .iso will be kept off the flash.
    pkgfile=%PKGFILE%
    base_pkgdir=/packages
    pkgdir=${pkgdir:-$base_pkgdir}
    pkgdir_mnt=$base_pkgdir/mnt
    base_mountdir=$pkgdir_mnt/$package
    base_mountpkg=$base_pkgdir/mount.$package
    base_umountpkg=$base_pkgdir/umount.$package

    mountdir=$pkgdir_mnt/$pkgfile
    mountpkg=$base_pkgdir/mount.$pkgfile
    umountpkg=$base_pkgdir/umount.$pkgfile

    if [ -z $PKG_BOOTSTRAP ] ; then
        [ -d $pkgdir ] || /bin/mkdir -p $pkgdir
    fi
    clean_pkg_list=

    # jbundle and/or package.sh set this to a file, so that
    # we can detect across packages that a reboot is needed.
    PKG_NEED_TO_REBOOT=${PKG_NEED_TO_REBOOT:-/dev/null}
    if [ -s $PKG_NEED_TO_REBOOT ]; then
        . $PKG_NEED_TO_REBOOT
    fi
    DebugOff initialize
}

warn() {
    if [ -z "$1" ]; then
	echo ""
    else
	echo "WARNING:" "$*"
    fi
}

error() {
    if [ -z "$1" ]; then
	echo ""
    else
	echo "ERROR:" "$*"
	if [ -z "$PKG_FORCE" ]; then
	    exit 1
	fi
    fi
}

#
# dire_warn <message> ...
#
# Warns with a fist
#
dire_warn() {
    warn "$@"
    if [ -z "$PKG_FORCE" ]; then
	warn_abort
    fi
}

notice() {
    if [ -z "$1" ]; then
	echo ""
    else
	echo "NOTICE:" "$*"
    fi
}

inform() {
    if [ -z "$PKG_QUIET" ]; then
	echo "$*"
    fi
}

#
# warn_abort
#
# When something is wrong, bail. When something is very wrong, bail faster.
#
warn_abort() {
    warn
    warn "This installation attempt will be aborted.  If you"
    warn "wish to force the installation despite these warnings"
    warn "you may use the 'force' option on the command line."
    exit 1
}


#
# verify_pkg hash
#
# If there is a file "hash" we check that
# "hash_cmd" < "pkg" == `cat "hash"`
# We determine "hash_cnd" from the extention of "hash"
# and "pkg" is "hash" with its ."hash_ext" extention stripped.
#
verify_pkg() {
    DebugOn verify_pkg
    local pkg hash hash_cmd hash_desc hash_ext want have

    hash=$1

    if [ -s $hash ]; then
	#
	# We only do md5 now, but allow for adding other methods
	#
	case "$hash" in
	*)  hash_cmd=md5
	    hash_ext=md5
	    hash_desc="MD5 checksum"
	    ;;
	esac

	# We rely on foo.tgz.$hash_ext being the $method hash
	pkg=`expr $hash : "\(.*\).$hash_ext"`

        want=`cat $hash`
        have=`$hash_cmd < $pkg`
        if [ x$have = x$want ]; then
            inform Verified $hash_desc of $pkg
	else
            error Failed $hash_desc of $pkg
            # ensure we do not proceed - even with PKG_FORCE set.
            exit 1
	fi
    fi
    DebugOff verify_pkg
}

#
# version_check
#
# Check package against base OS.
#
version_check() {
    DebugOn version_check
    # PKG_MIN_JUNOS_MAJOR is set by jbundle's +INSTALL
    local major_re=${1:-$PKG_JUNOS_MAJOR_OK}

    case "$major_re" in
    \[[1-9]*) ;;
    [1-9]*)	
        if [ $major_re -lt %RELEASE_MAJOR% ]; then
	    major_re="[${major_re}-%RELEASE_MAJOR%]"
        else
            major_re="[%RELEASE_MAJOR%-$major_re]"
	fi
        ;;
    *)	major_re="%RELEASE_MAJOR%";;
    esac
    grep -qs "$major_re\.[0-9]" /etc/db/pkg/junos/+COMMENT
    if [ $? != 0 ] ; then
	warn
	warn "This base version of JUNOS will not properly"
	warn "support this package.  Please install base OS"
	warn "JUNOS %RELEASE_MAJOR%.0 or newer ASAP.  You can do this via"
	warn "a jinstall package or install-media."
	case "./$package" in
	*/jbundle*) # nothing removed yet, so no need to rollback.
	    ;;
	*)  # previous package has likely been removed so be helpful.
	    warn
	    warn "Or use the command:"
	    warn
	    warn "	'request system software rollback'"
	    warn
	    warn "to attempt to restore the previous software set."
	    ;;
	esac
	warn
	warn "This installation attempt will be aborted."
	warn
	exit 1
    fi
    DebugOff version_check
}

#
# storage_check
#
# Check to make sure we've got enough space.
#
storage_check() {
    DebugOn storage_check
    local minfree=${1:-2048}

    if [ -z "$PKG_STORAGE_CHECK_DISABLED" ]; then
	available=`df -k / | awk 'NR==2 { print $4 }'`
	suggested=`du -ks $instmp | awk '{ print $1}'`

	# make sure root always has $minfree mb to spare
	suggested=`expr $suggested + $minfree`

	if [ $suggested -ge $available ] ; then
	    warn
	    warn "The root filesystem is low on free disk space."
	    warn "This package requires ${suggested}k free, but there"
	    warn "is only ${available}k available."

	    warn_abort
	fi
    else
	trace Storage check is disabled
    fi
    DebugOff storage_check
}

#
# dot_file <package-name> [quietly]
#
# Dot (source) a package REQUIRE script, to pick up variable settings
#
dot_file() {
    local dot_path

    PKG_SETUP_VARIABLES_ONLY=TRUE

    dot_path="$pkg_db_dir/$1$pkg_tag/+REQUIRE"
    trace Dotting file $dot_path ...

    if [ "$1$pkg_tag" = "$package" ]; then
	trace Dot file $dot_path is us
	if [ -r ./+REQUIRE ]; then
	    . ./+REQUIRE
	else
	    warn "Local requirements file for package $1 not found"
	fi
    elif [ ! -r $dot_path ]; then
	trace Dot file $dot_path does not exist
	if [ -z "$2" ]; then
	    warn "Could not open requirements file for $1$pkg_tag: $dot_path"
	fi
    elif grep -sq PKG_SETUP_VARIABLES_ONLY $dot_path; then
	. $dot_path
    else
	if [ -z "$2" ]; then
	    warn "Package '$1' is not compatible with package '$package':"
	    warn "    $1 does not support requirements tests (fatal)"
	    fail=1
	fi
    fi
}

#
# var_warn <my-name> <my-value> <test> <their-name> <their-value> <message>
#
# Warn (and bail) if the variables don't match
#
var_warn() {
    trace testing: "$@"
    if [ "$2" "$3" "$5" ]; then
	warn "Package '$1' is not compatible with package '$4':"
	warn "    $6"
        warn "    ($1:$2 $3 $4:$5)"
        fail=1
    fi
}

#
# package_exists <package-name>
#
# return true if the package exists. Use this function for juniper packages
#
package_exists() {
    trace package_exists tests $1 `ls -ld /etc/db/pkg/$1$pkg_tag 2>/dev/null`
    if [ -d /etc/db/pkg/$1$pkg_tag ]; then
	trace package_exists: "$1" is installed
	true
    elif [ "$1$pkg_tag" = "$package" ]; then
	trace package_exists: "$1" is us
	true
    else
	trace package_exists: fails for "$1"
	false
    fi
}

#
# package_installed <package-name>
#
# return true if the package exists. Use this function for non-juniper
# packages.
#
package_installed() {
    trace package_installed tests $1 `ls -ld /etc/db/pkg/$1 2>/dev/null`
    if [ -d /etc/db/pkg/$1 ]; then
	trace package_installed: "$1" is installed
	true
    elif [ "$1" = "$package" ]; then
	trace package_installed: "$1" is us
	true
    else
	trace package_installed: fails for "$1"
	false
    fi
}

#
# package_does_not_exist <package-name>
#
package_does_not_exist() {
    if package_exists "$1" ; then
	false
    else
	true
    fi
}

daemon_restart_warn() {
    echo "WARNING: Daemons could not be restarted:" "$*"
}

#
# daemon_restart_other <daemon-name>
#
# Restart a daemon by means other than rpdc
#
daemon_get_pid() {
    if [ -r /var/run/$1.pid ]; then
	cat /var/run/$1.pid
    else	
	ps gax | grep "/$1 -N" | grep -v grep | awk '{ print $1 }' 2>/dev/null
    fi
}
                    
daemon_kill_other() {
  local daemon_pid=`daemon_get_pid "$@"`
  if [ ! -z "$daemon_pid" ]; then
      kill -TERM "$daemon_pid"
  fi
}

daemon_restart_other() {
    echo "Restarting $1 ..."
    daemon_kill_other "$@"
}

#
# daemon_restart <daemon-name>
#
# restart a daemon by whatever means available; normally, this means that
# we kill it (using rpdc is possible) and init restarts it
#
daemon_kill() {
    if [ -x /usr/sbin/rpdc ]; then
	rpdc -q -D$1 stop
    else
	daemon_kill_other $1
    fi
}

daemon_restart() {
    echo "Restarting $1 ..."
    daemon_kill "$@"
}

#
# daemon_is_running <daemon-name>
#
daemon_is_running() {
    if [ -x /usr/sbin/rpdc ]; then
	rpdc -q -D$1 running	
    else
	false
    fi
}

#
# need_to_reboot
#
# Determine if we need to reboot after software install
#
need_to_reboot() {
    need_to_reboot_rc=${need_to_reboot_rc:-false}

    if [ "$need_to_reboot_rc" = true ]; then
        # we've been here before and already made up our mind
        return 0
    fi
    
    #
    # If the running kernel has no +REQUIRE script variables,
    # it's an oldie and we definitely want to reboot.
    #
    dot_jkernel_require
    if [ ! -r $jkernel_require ]; then
        need_to_reboot_rc=true
    fi
    
    if package_exists jkernel ; then
	if [ -z "$jkernel_works" ]; then
	    dot_file jkernel quietly
	fi
	if [ ! -z "$jkernel_works" ]; then
	    if jkernel_needs_to_reboot ; then
		need_to_reboot_rc=true
	    fi
	fi
    fi

    if package_exists jbase ; then
	if [ -z "$jkernel_works" ]; then
	    dot_file jkernel quietly
	fi
	if [ ! -z "$jkernel_works" ]; then
	    if jkernel_needs_to_reboot ; then
		need_to_reboot_rc=true
	    fi
	fi
    fi

    if package_exists jroute ; then
	if [ -z "$jroute_works" ]; then
	    dot_file jroute quietly
	fi
	if [ ! -z "$jroute_works" ]; then
	    if jroute_needs_to_reboot ; then
		need_to_reboot_rc=true
	    fi
	fi
    fi

    if package_exists jpfe ; then
	if [ -z "$jpfe_works" ]; then
	    dot_file jpfe quietly
	fi
	if [ ! -z "$jpfe_works" ]; then
	    if jpfe_needs_to_reboot ; then
		need_to_reboot_rc=true
	    fi
	fi
    fi
    if [ "$need_to_reboot_rc" = true ]; then
        echo need_to_reboot_rc=true >> $PKG_NEED_TO_REBOOT
    fi
    $need_to_reboot_rc
}

#
# user_wants_reboot
#
# Does the user intend on rebooting after we exit? If so, there's no
# need to restart/rebuild/retool anything.
#
user_wants_reboot() {
    trace user_wants_reboot: $PKG_USER_WILL_REBOOT
    [ ! -z "$PKG_USER_WILL_REBOOT" ];
}

#
# user_wants_to_delay
#
# Does the user want to delay? This may be by choice, and may be
# because the software is not being installed into the running system.
#
user_wants_to_delay() {
    trace user_wants_to_delay: $PKG_USER_WANTS_TO_DELAY
    [ ! -z "$PKG_USER_WANTS_TO_DELAY" ];
}

#
# save_current_configuration
#
# If the database exists, we try to save it in ascii form using the
# previous package's mgd (mgd.last from POST-INSTALL). If the saved
# version if different that the last committed version, or if there
# is no committed version, let the user know where the save file is.
#
save_current_configuration() {
    DebugOn save_current_configuration
    local saving_mgd

    trace save_current_configuration

    if [ "x$PKG_SAVE_CURRENT_CONFIGURATION" != x ]; then
	# we've been here before.
	return
    fi
    if [ -f $mgd ]; then
	saving_mgd=$mgd
    else
	saving_mgd=$mgd_last
    fi

    if [ -f $config_database -a -x $saving_mgd ] ; then
	$saving_mgd -e $config_changes > /dev/null 2>&1
	if [ -f $config_changes ] ; then
	    if [ -f $config_file ] ; then
                case $config_file in
		*.gz) gunzip < $config_file | diff -q $config_changes - > /dev/null;;
		*) diff -q $config_file $config_changes > /dev/null;;
		esac
		if [ $? != 0 ]; then
		    notice "uncommitted changes have been saved in $config_changes"
		fi
	    else
		notice "uncommitted database has been saved in $config_changes"
	    fi
	fi
	# avoid doing this more than once
	echo PKG_SAVE_CURRENT_CONFIGURATION=: >> $PKG_NEED_TO_REBOOT
    fi
    DebugOff save_current_configuration
}

#
# restart_mgd
#
# We need to restart the management daemon, if possible. This involves
# rebuilding the schema, since the incoming package should have dd.so
# shared libraries that affect it. This operation implicitly reloads
# the configuration database. We then run a commit, to make the
# configuration really happen. Then we restart the mgd daemon itself.
#
restart_mgd() {
    local rc mgd_running
    trace restart_mgd

    [ $package = jroute -o -d $pkg_db_dir/jroute ] ||  { 
	trace no jroute package
	return
    }
    [ -x $mgd ] || { trace $mgd not available; return; }

    # Save the old config binary database. If there is a committed
    # version, reload it. I don't reload the uncommitted changes.
    if [ -f $config_database ] ; then
	mv $config_database $config_database.old
    fi

    rc=false
    daemon_is_running mgd
    mgd_running=$?

    if [ -f $config_file ] ; then
	cp -p $config_file /var/db/$config_file.post-install
	echo "Reloading $config_file ..."
	$mgd build-schema
	if [ $? -ne 0 ]; then
	    warn "Errors found while loading configuration."
	    warn "Correct the errors and commit the configuration."
	    rc=true
	else 
	    echo "Activating $config_file ..."
	    $mgd activate
	    if [ $? -ne 0 ]; then
		rc=true
	    fi
	fi
    fi

    # mgd should be running already; stop it and init will restart it
    # If it wasn't running, kicking init should have started it for us.
    if [ $mgd_running = 0 ]; then
	daemon_restart mgd
    fi
    kill -HUP 1

    $rc
}

#
# restart_watchdog
# 
# Restart watchdog daemon
#
restart_watchdog () {
    local pid

    echo "Restarting watchdog ..."
    pid=`ps gax | grep "$1 -t" | grep -v grep \
	 | awk '{ print \$1 }' 2>/dev/null`
    if [ ! -z "$pid" ]; then
	kill -TERM "$pid"
    else
	warn "restart_watchdog: Watchdog process not found"
    fi
    #
    # HUP init for good measure
    kill -HUP 1
}

#
# all_packages_exist [quietly]
#
# Determine if we have a complete set of software
#
all_packages_exist() {
    local all_packages_exists_rc
    all_packages_exists_rc=true

    all_packages_exist_test jkernel $1
    all_packages_exist_test jroute $1
    all_packages_exist_test jpfe $1
    $all_packages_exists_rc
}

all_packages_exist_test() {
    if package_does_not_exist "$1" ; then
	trace all_packages_exist: package_does_not_exist "$1"
	if [ -z "$2" ]; then
	    warn "Package "$1" is not installed"
	fi
	all_packages_exists_rc=false
    fi
}

warn_of_reboot() {
    # after we've been through here once, PKG_WARN_DELAY
    # will be ':' and so these lines will be commented out.
    $PKG_WARN_DELAY warn "A reboot is required to load this software correctly"
    # jbundle calls us with an arg of jboot if he needs to update
    # it, when this happens all_packages_exist will do the wrong thing
    # since we've not removed anything yet, so we skip it.
    if [ "$1" != jboot ] && all_packages_exist quietly ; then
        $PKG_WARN_DELAY warn "    Use the 'request system reboot' command immediately"
    else
        $PKG_WARN_DELAY warn "    Use the 'request system reboot' command"
	$PKG_WARN_DELAY warn "        when software installation is complete"
    fi
    $PKG_WARN_DELAY echo PKG_WARN_DELAY=: >> $PKG_NEED_TO_REBOOT
    PKG_WARN_DELAY=:
}

#
# check_delay
#
#
check_delay() {
    if user_wants_reboot ; then
	trace check_delay: user_wants_reboot
	# hold your tongue
	true
    elif user_wants_to_delay ; then
	trace check_delay: user_wants_to_delay
	warn "Daemons will be restarted at a later time"
	true
    elif need_to_reboot ; then
	trace check_delay: need_to_reboot
        warn_of_reboot
	true
    else
	false
    fi
}

#
# kick_off_other_daemons <daemon-name> ...
#
# Restart whatever non-conformant daemons
#
kick_off_other_daemons() {
    local kick_list restart_list daemon

    if check_delay ; then
	trace kick_off_daemons: delaying
	# hold your tongue
	true
    else 
	restart_list="$*"
	trace kick_off_other_daemons: get to work
	# Restart daemons by stopping them and letting init restart them
	for daemon in $restart_list ; do
	    trace kick_off_other_daemons: restarting $daemon
	    daemon_restart_other $daemon
	done

	# HUP init once more just to be safe....
	kill -HUP 1

	false
    fi
}

#
# kick_off_daemons <daemon-name> ...
#
# Restart whatever daemons are required to get this thing cooking
#
kick_off_daemons() {
    local kick_list restart_list daemon

    if check_delay ; then
	trace kick_off_daemons: delaying
	# hold your tongue
	true
    elif package_does_not_exist jroute; then
	trace kick_off_daemons: no jroute
	# after we've been through here once, PKG_WARN_RESTART_JROUTE
	# will be ':' and so these lines will be commented out.
	$PKG_WARN_RESTART_JROUTE warn "Daemons will be restarted when the jroute package is installed"
	$PKG_WARN_RESTART_JROUTE echo PKG_WARN_RESTART_JROUTE=: >> $PKG_NEED_TO_REBOOT
	PKG_WARN_RESTART_JROUTE=:
	false
    else 
	kick_list="$*"
	trace kick_off_daemons: get to work
	restart_list=""
	for daemon in $kick_list ; do
	    if [ "$daemon" = "mgd" ]; then
		# skip mgd
	    else
		daemon_is_running $daemon
		if [ $? -eq 0 ]; then
		    restart_list="$restart_list $daemon"
		fi
	    fi
	done

	if restart_mgd $kick_list; then
	    trace kick_off_daemons: restart_mgd failed
	    # Restarting mgd failed. We need to decide whether we
	    # can restart our daemons
	    # Don't do anything for now....
	    false
	else

	    # MGD should have just HUPped init
	    # kill -HUP 1

	    # Restart daemons by stopping them and letting init restart them
	    for daemon in $restart_list ; do
		trace kick_off_daemons: restarting $daemon
		daemon_restart $daemon
	    done

	    # HUP init once more just to be safe....
	    kill -HUP 1

	    false
	fi
    fi
}

#
# md5_cksum_value <file>
#
# Get the MD5 checksum value for a file 
#
md5_cksum_value() {
    md5 "$1" 2>/dev/null | awk '{print $4}' 2>/dev/null
}

#
# what_filesystem <file>
#
# Determine which filesystem a given file is mounted on, if any
#
what_filesystem () {
    df $1 | grep -v Filesystem | awk '{print $1}' 2>/dev/null
}

#
# which <cmd-file>
#
# We don't ship /usr/bin/which, so we have to fake one
#
which() {
    local which_found
    which_found=""
    for dir in /sbin /usr/sbin /bin /usr/bin /usr/libexec ; do
	if [ -x "$dir/$1" -a -z "$which_found" ]; then
	    echo "$dir/$1"
	    which_found="done"
	fi
    done
}

#
# daemon_needs_restarted <daemon-name>
#
# Determine if the daemon needs to be restarted based on the md5 checksum
# of the running image and it's disk file
# Note that with packages mounted in ISO filesystems now, we could have
# the same file with matching MD5s but in two different filesystems - we
# to make sure we report true in this case
#
daemon_needs_restarted() {
    local pid daemon_md5 binary_file binary_md5 daemon_fs binary_fs

    if [ -r /var/run/$1.pid ]; then
	pid=`cat /var/run/$1.pid`
	if [ -r /proc/$pid/file ]; then
	    daemon_md5=`md5_cksum_value /proc/$pid/file`
	    binary_file=`which $1`
	    if [ -z "$binary_file" ]; then
	        trace "daemon_needs_restarted: no binary for $1"
		false
	    else
		binary_md5=`md5_cksum_value $binary_file`
		#
		# Ok, if their MD5s are the same, they could still be on
		# different filesystems, so let's check that as well
		if [ "$daemon_md5" = "$binary_md5" ]; then
 		    daemon_fs=`what_filesystem /proc/$pid/file`
		    binary_fs=`what_filesystem $binary_file`
		    [ "$daemon_fs" != "$binary_fs" ]
		else
		    true
		fi
	    fi
	else
	    #
	    # There was a pid file but we found no process with that pid...
	    # this is a race condition and init has restarted the daemon.
	    # We'll ask for a restart anyway.
	    #
	    trace "daemon_needs_restarted: pidfile but no process for $1"
	    true
	fi
    else
	trace "daemon_needs_restarted: no pidfile for $1"
	true
    fi
}

#
# consider_kicking_daemons <daemon-name> ...
#
# Consider each of the daemons given as arguments; if the running version
# is not the version on disk, restart it.
#
consider_kicking_daemons() {
    local kick_list daemon

    if user_wants_reboot ; then
	trace consider_kicking_daemons: user_wants_reboot
    elif user_wants_to_delay ; then
	trace consider_kicking_daemons: user_wants_to_delay
    elif need_to_reboot ; then
	trace consider_kicking_daemons: need_to_reboot
    elif [ ! -x $mgd ]; then
	trace consider_kicking_daemons: no mgd
    else 
	kick_list="$*"
	trace consider_kicking_daemons: get to work

	# Restart daemons by stopping them and letting init restart them
	for daemon in $kick_list ; do
	    trace consider_kicking_daemons: considering $daemon
	    if [ "$daemon" = "mgd" ]; then
		# skip mgd
	    elif daemon_needs_restarted $daemon; then
		trace consider_kicking_daemons: restarting $daemon
		daemon_restart $daemon
	    else
		rpdc -D$daemon reconfig
	    fi
	done
    fi
}

#
# create_mount_package
#   Create script to mount specified package
#
# args
# $1  - package-path to mount
# $2  - mount point for package

create_mount_package () {
    DebugOn create_mount_package
    local pkgpath mountpoint
 
    pkgpath=$1
    mountpoint=$2

    # We create a mount script that will stand being run twice during
    # boot. The first time, core packages should be mounted, but
    # optional ones - that have their .iso's on /var should silently
    # give up if the pkgpath isn't available.
    #
    # During the second pass - after /var is mounted, we don't want
    # to bleat about being already mounted, but we do want to complain
    # about any missing pkgpaths.
    # 
cat <<EOF
:
case "\$1" in
optional)
    core=:; optional=echo;;
*)  core=;  optional=:;;
esac
# for the benefit of cleanup-pkgs
pkgpath=$pkgpath
if [ ! -s $pkgpath ]; then
    pkgdir=`dirname $pkgpath`
    # if pkgdir is not present, we'll pick it up in second round
    # so keep quiet now
    if [ -d \$pkgdir ]; then
	echo $pkgpath not present.
    else
        \$optional echo \$pkgdir not present.
    fi
    exit 1
fi
mounted=\`/sbin/mount | /usr/bin/grep " $mountpoint "\`
case "\$mounted" in
*/*) \$core echo $pkgpath already mounted; exit 0;;
esac

u=1
while [ \$u -lt 99 ]
do
    vnd=vn\$u
    if /sbin/vnconfig -q -c -s compressed \$vnd $pkgpath autoffset; then
        if /sbin/mount -t cd9660 -r /dev/\$vnd $mountpoint; then
	    echo "Mounted $package package on /dev/\$vnd..."
            exit 0
	else
	    echo "Unable to mount $package on /dev/\$vnd"
            /sbin/vnconfig -u -v /dev/\$vnd
            exit 1
	fi
    fi
    u=\`expr \$u + 1\`
done
echo "Unable to mount $package - no more vn devices"
exit 1
EOF
    DebugOff create_mount_package
}

#
# Create script to unmount specified package
#
# $1 - mount point

create_umount_package () {
    DebugOn create_umount_package
    local mountpoint

    mountpoint=$1

    cat <<EOF
:
/sbin/mount | /usr/bin/grep " $mountpoint " |
while read vnd junk
do
    if /sbin/umount $mountpoint; then
        echo "Unmounted $mountpoint ..."
        /sbin/vnconfig -u -v \$vnd || echo "Unable to unconfigure \$vnd"
    fi
done
EOF
    DebugOff create_umount_package
}

#
# Create links for package related scripts/mounts
#
make_package_links () {
    DebugOn make_package_links
    /bin/mkdir -p $mountdir
    /bin/rm -df $base_mountdir
    make_symlink ${mountdir##*/} $base_mountdir 
    if [ $base_pkgdir = $pkgdir ]; then
	make_symlink $pkgfile $base_pkgdir/$package
    else
	make_symlink $pkgdir/$pkgfile $base_pkgdir/$package
    fi
    if [ -s $mountpkg ]; then
	make_symlink ${mountpkg##*/} $base_mountpkg
	/bin/chmod 0755 $mountpkg
	make_symlink ${umountpkg##*/} $base_umountpkg 
	/bin/chmod 0755 $umountpkg
    fi
    DebugOff make_package_links
}

#
# check_installed
#
# Check to see if this exact version of this package is already installed
#
check_installed () {
    local pkglink

    if [ -d /etc/db/pkg/$package -a -f $pkgdir/$pkgfile -a -d $mountdir ]; then
        case `/bin/ls -l $base_mountdir` in
	*"> $mountdir")
	    warn "This version of $package is already installed on this system"
	    return 0
            ;;
	esac
    fi
    false
}

# compensate for lack of cmp(1)
cmp() {
    case "$1" in
    -s) shift;;
    esac
    diff $* > /dev/null 2>&1
}

#
# replace $file with $file.new if appropriate 
#
install_if_new() {
    local file=$1
    local new=${NewExt:-new}
    local old=${OldExt:-old}
    
    if [ -s $file.$new ]; then
	if [ -f $file ]; then
	    if cmp -s $file $file.$new; then
		rm -f $file.$new
	    else
                rm -f $file.$old
                mv $file $file.$old
	    fi
        fi
    else
        rm -f $file.$new
    fi
    if [ -s $file.$new ]; then
        mv $file.$new $file
        :
    fi
}

#
# get_lock [lock] [iflocked]
# Implements mutual exclusion based on content of "lock"
# If we return from here then we have the mutex.
# If iflocked is "waitfor" we will wait for the current locker to exit
# and retry rather than simply exit with $iflocked as status (default 1).
#
get_lock() {
	lock=${1:-$pkg_LCK}
	iflocked=${2:-1}
	tlock=$lock.$$
	ltty=`expr ${CLI_TTY:-__} : '.*\(..\)$'`
	case $ltty in
	__) ltty=unknown;;
	esac
	ldate=`date "+%Y-%m-%d %H:%M %Z"`

	while :
	do
		lpid=
		echo "lpid=$$ ldesc=\"user ${CLI_USER:-unknown} terminal $ltty, process $$, started at $ldate\"" > $tlock
		ln $tlock $lock > /dev/null 2>&1 && break
		rm -f $tlock	# avoid mess
		# 
		# we are going to eval the content of the lock
		# but _not_ if it contains anything other than what we expect
		#
		xl=`test -s $lock && grep -i '^lpid=[0-9][0-9]* ldesc="[a-z][a-z0-9:, -]*"$' $lock`
		case "$xl" in
		lpid=*)	eval $xl;;
		esac
		case "$lpid" in
		"")	# an empty or invalid lock file should never happen
			rm -f $lock; test -f $lock || continue
			error "cannot remove empty lock '$lock'"
			;;
		esac
		# we can't simply use return code, as permission denied means
		# locker is alive... watch out for internationalization!
		psts=`LANG=C LC_ALL=C kill -0 $lpid 2>&1`
		case "$psts" in
		*:*such*p*)
			rm -f $lock; test -f $lock || continue
			error "cannot remove old lock '$lock' held by $ldesc"
			;;	    
		esac
		# ok a valid lock exists, and it isn't us
		case "${iflocked:-1}" in
		waitfor)
		    # we want to wait for the lock, as long as it takes...
		    while :
		    do
			psts=`LANG=C LC_ALL=C kill -0 $lpid 2>&1`
			case "$psts" in
			*:*such*p*) rm -f $lock; break;;
			esac
			sleep 8
		    done
		    continue
		    ;;
		0)  # go quietly
		    exit 0
		    ;;
		[1-9]*)
		    echo "ERROR: Another package installation in progress:"
		    echo $ldesc
		    exit ${iflocked:-1}
		    ;;
		esac
	done
	rm -f $tlock
}
	    
fi # Close the 'if' from the top of the file (PKG_SETUP_VARIABLES_ONLY)
#!/bin/sh
#
# $Id: jinstall-header,v 1.23.12.2 2003/04/22 06:24:20 sjg Exp $
#
# Copyright (c) 2001-2003, Juniper Networks, Inc.
# All rights reserved.
#
# A common header used by all jinstall REQUIRE, INSTALL, and DEINSTALL
# scripts. Each time the script is called $1 is set to the package
# name and $2 is set to the instance. Based on the instance, the
# appropriate code gets executed.
#
# This script is run after the tar file has been unpacked into the /var
# sandbox area before anything has actually been moved to the final
# location, and then again after things have been moved into place.
#

#
# file_size()
#
# Compute the amount of space used by a bunch of files
#
file_size() {
    echo `du -ks $* 2>/dev/null | awk '{ sum += $1 } END { print sum }'`
}

#
# package_size()
#
# Compute the amount of space used by an installed package.
#
package_size() {
    local files
    files=`pkg_info -qL "$1" 2>/dev/null | awk '{ print $1 }'`
    if [ ! -z "${files}" ]; then
	file_size ${files}
    else
	echo 0
    fi
}


# tmp_storage_check()
#
# Check to make sure when the installer copies files to the /tmp directory
# it has enough space
#
tmp_storage_check() {

    #
    # size the tmp based on the amount of memory available. The formula is
    # Min(1/2 of memsize in "sectors" of 512B, 131072 sectors).
    #
    memsize=`sysctl -n hw.512bmem 2>/dev/null`
    if [ $? != 0 ]; then
	# older O.S. versions do not support "sysctl -n hw.512bmem",
	# however these versions do not have large memory either. We can use:
	memsize=`sysctl -n hw.physmem`
	memsize=`expr $memsize / 512`
    fi
    available=`expr $memsize / 2`
    if [ "$available" -gt 131072 ] ; then
	available=131072
    fi

    #
    # sum the amount of space the configs will occupy
    #
    config_list=""
    [ -d /config ] && config_list="${config_list} /config"
    [ -d /var/config ] && config_list="${config_list} /var/config"
    config_suggested=`file_size $config_list`

    #
    # find out the amount of space the packages will occupy. This is
    # conservative. The bootstrap install space is added even though it
    # will not go on /tmp just to make calculations easy and allow for 
    # tmp file generated by the install script
    #
    filelist=`ls -R $instmp`
    package_suggested=`file_size $filelist`

    suggested=`expr ${package_suggested} + ${config_suggested}`

    if [ $suggested -ge $available ] ; then
	warn
	warn "The /tmp filesystem that is created by the next stage of"
	warn "the installer does not have sufficient space. This package"
	warn "requires ${suggested}k free (${config_suggested}k for configuration"
	warn "files and ${package_suggested}k for the new software), but there is"
	warn "only ${available}k available."
	dire_warn
    fi

}


# var_storage_check()
#
# Check that /var is not an emergency partition.
#
var_storage_check() {

    #
    # Check that /var is a hard disk, not an emergency var
    #
    vardrive=`df /var | grep -v Filesystem | awk '/^mfs/ {print "emergency"}'`
    trace "*** /var is on - ${vardrive} - (empty means on hard disk)"
    if [ "$vardrive" = "emergency" ] ; then
	warn
	warn "The /var drive is not mounted on the hard disk. This package"
	warn "requires that /var be mounted on the hard disk."
	dire_warn
    fi

    #
    # Check that hard disk is in the Boot List.
    #
    model=`sysctl -n hw.re.model`
    if [ "$model" = "teknor" -o "$model" = "force" ] ; then
	sysctl -n machdep.bootdevs|grep -q disk
	if [ $? != 0 ] ; then
	  warn
	  warn "This installation will not succeed."
	  warn "This installation requires the presence of the hard disk."
	  warn "The hard disk is missing from the Boot List."
	  warn "Try pcmcia card installation, to install only on compact-flash."
	  warn
	  warn "This installation attempt will be aborted."
	  warn
	  exit 1
	fi
    fi

    #
    # available space on /var
    #
    available=`df -k /var | awk '$1 != "Filesystem" { print $4 }'`
    trace "*** free space on /var: ${available}"
    
    #
    # suggested = space needed by pkg_add playpen. Playpen size is
    # four times the size of the package, but keep some buffer.
    #
    suggested=`file_size jbundle-5.7R2.4-export.tgz`
    suggested=`expr ${suggested} \* 8` 

    if [ $suggested -ge $available ] ; then
	warn
	warn "The /var filesystem is low on free disk space."
	warn "This package requires ${suggested}k free, but there"
	warn "is only ${available}k available."
	dire_warn
    fi

}


#
# root_storage_check()
#
# Check to make sure we've got enough space in root to untar the
# bootstrap installer. 
#
root_storage_check() {

    #
    # If the jinstall target is compact-flash disk, check that it is
    # is in the Boot List.
    # Note: We do not check for hard disk because if it is not in the
    #       Boot List, jinstall will not pass the var_storage_check()
    #       anyway.
    #
    installdrive=`df / | awk '$6 == "/" {print substr($1, 6, 3)}'`
    installdrive="w${installdrive#[war]}"
    if [ "${installdrive#[wa]}" = "d0" ] ; then
      model=`sysctl -n hw.re.model`
      if [ "$model" = "teknor" -o "$model" = "force" ] ; then
	sysctl -n machdep.bootdevs|grep -q compact-flash
	if [ $? != 0 ] ; then
	    warn
	    warn "This installation will not succeed."
	    warn "This installation requires the presence of the compact-flash."
	    warn "The compact-flash is missing from the Boot List."
	    warn
	    warn "This installation attempt will be aborted."
	    warn
	    exit 1
	fi
      fi
    fi
    #
    # available space on root
    #
    available=`df -k / | awk '$1 != "Filesystem" { print $4 }'`
    trace "*** free space on /: ${available}"
    
    #
    # suggested = space occupied by bootstrap-install
    #
    suggested=0
    size=`tar tvf  bootstrap-install-5.7R2.4.tar | \
	      awk '{ sum = sum + ($3 / 1024) + 4 } END { print int(sum) }'`
    suggested=`expr ${suggested} + ${size}`

    #
    # Make sure root always has 2mb to spare. Remember, we'll get
    # lots more space back when the running daemons are restarted.
    #
    suggested=`expr ${suggested} + 2048`

    trace "*** suggested space: ${suggested}"
    
    if [ $suggested -ge $available ] ; then
	warn
	warn "The root filesystem is low on free disk space."
	warn "This package requires ${suggested}k free, but there"
	warn "is only ${available}k available."
	dire_warn
    fi
}


# save_configs
#
# Save configs into a tar file called configs-<release>.tgz
#
save_configs() {

    #
    # if this is occuring during a media installation (such as
    # installing on an olive with  floppies) the PKG_BOOTSTRAP will be
    # set and we can return immediately
    #
    if [ "$PKG_BOOTSTRAP" != "" ] ; then
	return
    fi

    inform "Saving the config files ..."

    save_current_configuration

    config_list=""
    [ -d /config ] && config_list="${config_list} config"
    [ -d /var/db/config ] && config_list="${config_list} var/db/config"
    if [ -f "$config_changes" ] ; then
	local f
	f=`echo $config_changes | sed -e 's,^/,,'`
	config_list="${config_list} $f"
    fi

    ssh_list=`echo /etc/ssh*`
    if [ "$ssh_list" != "/etc/ssh*" ] ; then
	local f g
	for f in $ssh_list ; do 
	    g=`echo $f | sed -e 's,^/,,'`
	    config_list="${config_list} $g"
	done
    fi

    # we now wack /var/etc/*.conf before restoring these,
    # so make sure we keep critical ones.
    var_file_list="var/etc/group \
var/etc/master.passwd \
var/etc/inetd.conf \
var/etc/pam.conf \
var/etc/resolv.conf \
var/etc/syslog.conf \
var/etc/localtime \
etc/localtime \
var/etc/exports"
    for f in $var_file_list ; do
	[ -f "/$f" ] && config_list="${config_list} $f"
    done

    if [ "$config_list" != "" ] ; then
	# If/when we have more files to exclude we can use
	# --exclude-from file
	# Note that -czf is required rather than cfz
	tar -czf $PKG_PREFIX/configs-5.7R2.4.tgz -C / --exclude etc/ssh/primes $config_list
	if [ $? != 0 ] ; then
	    warn
	    warn "Backup of configuration files failed"
	    warn
	    dire_warn
	fi
    fi
}


# uninstall_configs
#
# Delete the config tarball
#
uninstall_configs() {

    inform "Deleting saved config files ..."
    rm -f $PKG_PREFIX/configs-5.7R2.4.tgz

}


#
# install_bootstrap <bootstrap-install-pathname>
#
# Installs the bootstrap installer, and rewrites the boot block so 
# that the next reboot gives control to the bootstrap installer
#
install_bootstrap() {

    #
    # if this is occuring during a media installation (such as
    # installing on an olive with  floppies) the PKG_BOOTSTRAP will be
    # set and we can return immediately
    #
    if [ "$PKG_BOOTSTRAP" != "" ] ; then
	return
    fi

    inform "Installing the bootstrap installer ..."

    if [ -f "/boot/loader.conf" ] ; then
	mv /boot/loader.conf /boot/.loader.conf.backup
    fi

    tar xf $PKG_PREFIX/bootstrap-install-5.7R2.4.tar -C / || fail=1

    if [ "$fail" = "1" ] ; then
	warn
	warn "Install of the bootstrap installer failed"
	warn
	uninstall_bootstrap
	warn_abort
    fi

    trace "Installing new boot loaders"
    installdrive=`df / | awk '$6 == "/" {print substr($1, 6, 3)}'`
    installdrive="w${installdrive#[war]}"
    disklabel -B -b /boot/boot1 -s /boot/boot2 $installdrive
    if [ $? != 0 ] ; then
	warn
	warn "Failed while trying to install bootstrap loaders"
	warn
	uninstall_bootstrap
	warn_abort
    fi

    if [ "${installdrive#[wa]}" != "d0" ] ; then
	model=`sysctl -n hw.re.model`
	if [ "$model" = "teknor" -o "$model" = "force" ] ; then
	    sysctl -w 'machdep.nextbootdev=disk' > /dev/null 2>&1
	elif [ "$model" = "cpv5000" ] ; then
	    sysctl -w 'machdep.bootsuccess=2' > /dev/null 2>&1
	fi
    fi
}


# uninstall_bootstrap
#
# Undo the effects of untarring the bootstrap installer. 
#
uninstall_bootstrap() {

    inform "Deleting bootstrap installer ..."

    if [ -f "/boot/.loader.conf.backup" ] ; then
	mv /boot/.loader.conf.backup /boot/loader.conf
    fi
    rm -f /boot/installer
    rm -f /boot/mdimg.gz

    installdrive=`df / | awk '$6 == "/" {print substr($1, 6, 3)}'`
    installdrive="w${installdrive#[war]}"
    disklabel -B -r $installdrive

}

#
# create_settings_file <settings-file>
#
# Create a file with all the settings for the bootstrap-installer
#
create_settings_file() {
    local altdrive=""

    installdrive=`df / | awk '$6 == "/" {print substr($1, 6, 3)}'`

    # if mirroring is enabled, install on mirror subdisk as well
    if [ "$installdrive" = "rd0" ] ; then
	altdrive=`cat /etc/fstab | awk '$2 == "/altroot" {print substr($1, 6, 3)}'`
    fi
    installdrive="w${installdrive#[war]}"
    if [ $? != 0 ] ; then
	error "Error while creating settings file for the bootstrap installer"
    fi
    echo "installdrive='${installdrive} ${altdrive}'" > $1
    echo "ospackage=jboot-5.7R2.4" >> $1
    echo "osedition=export" >> $1
    echo "osrelease=5.7R2.4" >> $1
    echo "packlist='jbundle-5.7R2.4-export.tgz'" >> $1

    if [ -f $PKG_PREFIX/configs-5.7R2.4.tgz ] ; then
	echo "configpackage=configs-5.7R2.4.tgz" >> $1
    fi

    if [ ! -z "$PKG_TRACE_SHELL" ] ; then
	echo "set -x" >> $1
    fi
}


# preinstall_dialogue()
#
# This is the dialogue or monologue to inform the user what is going to happen.
#
preinstall_dialogue() {

    warn
    warn "    This package will load JUNOS 5.7R2.4 software."
    warn "    It will save JUNOS configuration files, log files, and SSH keys"
    warn "    (if configured), but erase all other files and information"
    warn "    stored on this machine.  This is the pre-installation stage"
    warn "    and all the software is loaded when you reboot the system."
    warn

}


# request_reboot
#
# This routine prints out the reboot instructions. Previously it would
# get a response from the user at the end of the install if they
# would like to proceed, but that turned out to be tricky. See PR14859
#
request_reboot() {

    warn
    warn "    A REBOOT IS REQUIRED TO LOAD THIS SOFTWARE CORRECTLY. Use the"
    warn "    'request system reboot' command when software installation is"
    warn "    complete. To abort the installation, do not reboot your system,"
    warn "    instead use the 'request system software delete jinstall'"
    warn "    command as soon as this operation completes."
    warn
   
    return
}


#!/bin/sh
#
# $Id: DEINSTALL,v 1.2 2001/04/29 06:29:34 abstine Exp $
#
# Copyright (c) 2001, Juniper Networks, Inc.
# All rights reserved.
#
# OS Update package installation script
#
# Most of the procedures are defined in jinstall-header. This script
# merely contains the logic.
#
#----------------------------------------------------------------------
# Main script
#----------------------------------------------------------------------

initialize "$@"

#
# called by the DEINSTALL script
#
if [ "$instance" = "DEINSTALL" ] ; then

    # remove the config files
    uninstall_configs

    # remove the bootstrap install files
    uninstall_bootstrap

fi

