#! /bin/sh
# 
# %Z%%M% %I% %E% SMI
# 
#  install_small_kernel 
# 
#  Copyright (c) 1989 by Sun Microsystems, Inc.
# 
#  This shell script installs a small preconfigured kernel for 
#  hardware configurations typically equipped with SCSI devices.  
#  It can be invoked from the miniroot, and from both single and
#  multi-user modes.
# 
#  The following host types are supported by this script:
# 	Standalone with SCSI disks only
# 	Server: If the server has non-SCSI disks, the small kernel
# 		can be installed on its clients having the supported
# 		configurations.  Otherwise, the user has the 
# 		option of installing the small kernel on the host 
# 		and each of the clients.
# 
#  	Dataless installs are supported only if this script is invoked
#  	in multi-user mode.  
# 
#  The script normally processes only those clients which aren't
#  flagged as having been installed with the small kernel.
#  You can force small kernel installation on specific hosts or speed
#  up the installation process by invoking the script and specifying
#  hostnames on the command line.
#

PATH=/bin:/usr/bin:/etc:/usr/etc:/usr/etc/upgrade:/usr/ucb ; export PATH
files_dir=/etc/install; script='install_small_kernel'
PWD=`pwd`; tmp=/tmp

usage="USAGE: $script [hostname1] [hostname2] [hostname3]..."
[ $# = 0 ] && default=1 && do_host=1 

if [ -f /.MINIROOT ]; then
	top='/a' && mini=1
else
	[ ! `whoami` = "root" ] && echo "Not superuser!" && exit 1
	ps -ax > /tmp/$$
	if egrep -s '[/ ]cron$' /tmp/$$ || egrep -s '[/ ]update$' /tmp/$$; then
		multi=1
	else
		single=1
	fi
fi

# 
# Make sure files created by suninstall are available
# 
for installfile in mount_list sys_info; do
	[ -s $files_dir/${installfile} ] && continue
	notfound="$notfound $installfile"
done

if [ "$notfound" ]; then
   echo "This utility depends on these files generated by 'suninstall':"
   echo "	$notfound."
   echo "They are not available on this system."; exit 1
fi

host_type=`awk -F= '$1 ~ /^sys_type$/ {print $2}' $files_dir/sys_info`

if [ "$mini" ] ; then
	sys_name=`awk -F= '$1 ~ /^hostname/ {print $2}' $files_dir/sys_info|\
	awk -F, '{print $1}'`
else
	sys_name=`hostname`
fi


# 
# Validate optional hostnames provided
# 
for i in $*; do
	case $i in
            $sys_name ) do_host=1;;
		    * ) if [ -s $files_dir/client.${i} ]; then
				clients="$clients $i"; continue
			fi
			notfound="$notfound $i";;
	esac
done

[ "$notfound" ] && echo "Unknown host: $notfound" && echo $usage &&  exit 1

# 
# Subroutine:  Process yes/no responses
# 
get_yn='(while read yn; do
	case "$yn" in
	   [Yy]* ) exit 0;;
	   [Nn]* ) exit 1;;
	       * ) echo -n "Please answer y or n:  ";;
     	esac
done)'


echo "


This utility installs a small pre-configured kernel for
systems which are either diskless, or equipped with
SCSI devices.  The kernel supports about four users for
the following diskfull or diskless configurations:

	Sun3/50 and Sun3/60 with up to 2 SCSI disks, 1 SCSI tape
	Sun3/80 with up to 4 SCSI disks, 2 SCSI tapes
	Sun4/110 with up to 4 SCSI disks, 2 SCSI tapes
	SPARCsystem 330 with up to 4 SCSI disks, 2 SCSI tapes
	SPARCstation 1, 1+, and 2 systems with up to 8 SCSI disks, 
			4 SCSI tapes, 2 CD-ROM drives, 1 Floppy Disk

If this system is a server that does not fit any of the above
configurations, this utility can be invoked to install the small
kernel on its clients listed above.
"

[ "$mini" ] && echo "Dataless systems are supported in multi-user mode only.
"

echo -n "Do you wish to continue? (y/n):  "
eval "$get_yn" || exit 1

wrong_config=\
"This utility installs a smaller generic kernel on 
systems having SCSI disks.  It appears that this machine
does not have the valid configuration that can be supported
by this utility."

no_dataless=\
"This utility does not support dataless clients from the miniroot.  
If you wish to install the small kernel, reboot your system and 
invoke it in multi-user mode."

if [ "$host_type" = "dataless" -a "$mini" ]; then
	echo "$no_dataless" && exit 1
fi

# 
# Subroutine:  Mount and unmount partitions; if operation fails,
# attempt error recovery
# 
get_mtstat='( [ "$do_mt" = "0" ] && cmd="mount" || cmd="umount"
tried=""; fixit=""
while :
do
	/etc/mount|grep -s "$mt_dir "
	[ "$?" = "$do_mt" ] && exit 0
	if [ "$tried" ]; then
		if [ "$do_mt" = "0" -a ! "$fixit" ]; then
		  /etc/umount $mt_dev && tried="" && fixit=1 && continue
	        fi
		echo -n "Unable to $cmd $mt_dir!  Try again? (y/n)  "
		eval "$get_yn" && continue || exit 1
	fi
	if [ "$do_mt" = 0 ]; then
		/etc/${cmd} $mt_dev $mt_dir && echo "$mt_dev $mt_dir" >> \
		$tmp/mt_$$
	else
		/etc/${cmd} $mt_dev
	fi
	tried=1
done )'

# 
# Subroutine:  Copy and verify the small kernel installed.
# If copy operation fails, try one more time and restore original
# version, if unsuccessful.
#
do_copy='( if [ ! -s $from/vmunix_small ]; then
		echo "Small Kernel not found in $from!"
		exit 1  
	   fi
	   if [ -f $to/vmunix ]; then
	      [ ! -s $to/vmunix.orig ] && mv $to/vmunix $to/vmunix.orig
	   fi
	   for i in 1 2; do
	   	cp $from/vmunix_small $to/vmunix
		sync; sync
	   	sum1=`$top/usr/bin/sum $from/vmunix_small`
		sum2=`$top/usr/bin/sum $to/vmunix`
	   	[ "$sum1" = "$sum2" ] && exit 0
	   	if [ "$i" = 2 ]; then
	   		echo "Unable to install small kernel for $sys_name!"
			[ ! -f $to/vmunix.orig ] && exit 1
	   		echo "Restoring default generic kernel..."
	   		mv $to/vmunix.orig $to/vmunix
			sync; sync
			exit 1 		
	      	fi
	   done
)'

# 
# Subroutine:  Before exiting, restore original filesystem mount state 
# and display appropriate completion message
# 
cleanup='( [ ! "$multi" ] && /etc/umount -at 4.2 > /dev/null 2>&1
	if [ -s $tmp/mt_$$ ] && [ ! "$mini" ] ; then
		do_mt=1
		cat $tmp/mt_$$ | while read mountlist; do
			set $mountlist
			mt_dev=$1; dir_nm=$2; 
			mt_dir=${top}$dir_nm
			eval "$get_mtstat" || break
		done
	fi
	rm -f $tmp/*_$$; cd $PWD
	if [ "$kern_ok" ]; then
	     echo ""
	     echo "The small pre-configured kernel has been installed on:"
	     echo "	$kern_ok"
	     [ "$mini" ] && echo "You may reboot your system now." || \
	     echo "You may reboot the system(s) now."
	else
	     echo "The small pre-configured kernel has not been installed."
	fi
exit 0 )'

# 
# Mount and verify root partition
# 

cd $files_dir
for i in `cat mount_list`; do
	case $i in
	  partition* )  disk=$i;;
	  mount_pt=/ )  rootdisk=`echo $disk | sed 's/.*=//g'`; break;;
		    *) ;;
	esac
done

do_mt=0; mt_dev=/dev/${rootdisk}; mt_dir=${top}
eval "$get_mtstat" 
[ ! "$?" = 0 ] && eval "$cleanup" && exit 1

trap 'echo $script ABORTED!; eval "$cleanup"; exit 1' 1 2 3 15

if [ ! -s $top/sbin/init ] ; then
	echo \
        "${rootdisk} does not appear to be the correct root partition!"
	eval "$cleanup" && exit 1
fi

#
# Check if host has non-SCSI disks
# If host=server with non-SCSI disks, install on clients only
#
disk_types=`awk '$1 ~ /^\/dev/ {print $1 }' ${top}/etc/fstab|\
	sed 's/^\/dev\///'`

if [ "$do_host" ] ; then
   for i in $disk_types; do
	case $i in
	    sd*|fd* )	;;
		  * ) 	do_host=
			[ ! "$host_type" = "server" ] && err=1 && break
			if [ "$default" ] || [ "$clients" ]; then
			    echo "Small kernel not installed on $sys_name." 
			    echo "Non-SCSI disk ($i) found..."
			else
				err=1
			fi
			break;;
	esac
		
   done
fi

[ "$err" ] && echo "$wrong_config" && eval "$cleanup" && exit 1

# 
# Mount all partitions 
# 

do_mt=0
awk ' $1 ~ /^\/dev/ { print $1 " " $2}' < ${top}/etc/fstab |\
while read mountlist; do
	set $mountlist
	mt_dev=$1; dir_nm=$2; 
	[ "$dir_nm" = "/" ] && continue
	[ "$dir_nm" = "/pcfs" ] && continue
	mt_dir=${top}$dir_nm
	eval "$get_mtstat" && continue
	eval "$cleanup" && exit 1
done

# 
# Install small kernel to host and verify it.
# If kernel can't be installed on server, query for clients.
#
if [ "$do_host" ] ; then
	echo -n "Install small kernel on $sys_name? (y/n)  "
	eval "$get_yn" || do_host=
fi

if [ "$do_host" ]; then
	to=$top
	from=${top}/usr/kvm/stand
	trap '' 1 2 3 15	
	eval "$do_copy"; stat=$?
	trap 'echo $script ABORTED!; eval "$cleanup"; exit 1' 1 2 3 15
	case $stat in
	     0) kern_ok="$kern_ok $sys_name"
		[ ! "$host_type" = "server" ] && eval "$cleanup" && exit 0 ;;
	     *) [ ! "$host_type" = "server" ] && eval "$cleanup"&& exit 1
		echo -n "Install small kernel on clients? (y/n)  "
		eval "$get_yn" 
		[ ! "$?" = 0 ] && eval "$cleanup" && exit 1;;
	esac	
fi

# 
# Get client info for server installations, using suninstall data files
# 
install_flag='small_kernel='

if [ "$default" ]; then
	ls client_list.* > $tmp/client_$$ 2>/dev/null
	if [ ! -s $tmp/client_$$ ] ; then
		echo "No clients have been set up for this server."
		eval "$cleanup" && exit 1
	fi
	clnt=`cat client_list.sun*`
else
	clnt=`echo $clients`
fi

[ ! "$clnt" ] && eval "$cleanup" && exit 0
skip='(small kernel previously installed).'
echo "Processing clients..."
last_clnt=`echo $clnt | awk '{print $NF}'`

for sys_name in $clnt; do
	cl_info=${files_dir}/client.${sys_name}
	if [ "$default" ]; then
		if grep -s ${install_flag}yes $cl_info; then
		     echo \
		     "Not processed: $sys_name $skip"
		     continue
		fi
	fi
	echo -n "Install small kernel on $sys_name? (y/n) "
	eval "$get_yn" || continue
	rpath=`awk -F= '$1 ~ /^root_path$/ {print $2}' $cl_info`
	to=${top}${rpath}
	kpath=`awk -F= '$1 ~ /^kvm_path$/ {print $2}' $cl_info`
	from=${top}${kpath}/stand
	if [ ! -d $to ]; then
		echo "Directory $to does not exist." && continue
	fi
	trap '' 1 2 3 15
	eval "$do_copy"; stat=$?
	trap 'echo $script ABORTED!; eval "$cleanup"; exit 1' 1 2 3 15
	case $stat in
		0) sed "s/^\($install_flag\).*/\1yes/" $cl_info > \
		   $tmp/$cl_info_$$
		   kern_ok="$kern_ok $sys_name"
		   cp -p $tmp/$cl_info_$$ ${cl_info}
		   [ "$mini" ]  && cp -p $tmp/$cl_info_$$ ${top}${cl_info};;
	        *) if [ ! "$sys_name" = "$last_clnt" ] ; then
			echo -n "Continue with other clients? (y/n)  "
			eval "$get_yn" && continue || break
		   fi
		   eval "$cleanup" && exit 1
	esac
done
			
eval "$cleanup" && exit 0
